From 39e84790d3b65a4af1ea1fb0d8f06c3ad75304b3 Mon Sep 17 00:00:00 2001 From: Alex Aizman Date: Thu, 4 Aug 2005 19:31:00 -0700 Subject: [SCSI] open-iscsi/linux-iscsi-5 Initiator: Header files open-iscsi-headers.patch - common header files: - iscsi_if.h (user/kernel #defines and user/kernel events); - iscsi_proto.h (RFC3720 #defines and types); - scsi_transport_iscsi.h (transport API, transport #defines and types). Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- include/scsi/iscsi_if.h | 245 ++++++++++++++++ include/scsi/iscsi_proto.h | 566 ++++++++++++++++++++++++++++++++++++ include/scsi/scsi_transport_iscsi.h | 202 ++++--------- 3 files changed, 866 insertions(+), 147 deletions(-) create mode 100644 include/scsi/iscsi_if.h create mode 100644 include/scsi/iscsi_proto.h (limited to 'include') diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h new file mode 100644 index 000000000000..be1bc792ab18 --- /dev/null +++ b/include/scsi/iscsi_if.h @@ -0,0 +1,245 @@ +/* + * iSCSI User/Kernel Shares (Defines, Constants, Protocol definitions, etc) + * + * Copyright (C) 2005 Dmitry Yusupov + * Copyright (C) 2005 Alex Aizman + * maintained by open-iscsi@googlegroups.com + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * See the file COPYING included with this distribution for more details. + */ + +#ifndef ISCSI_IF_H +#define ISCSI_IF_H + +#include + +#define UEVENT_BASE 10 +#define KEVENT_BASE 100 +#define ISCSI_ERR_BASE 1000 + +enum iscsi_uevent_e { + ISCSI_UEVENT_UNKNOWN = 0, + + /* down events */ + ISCSI_UEVENT_CREATE_SESSION = UEVENT_BASE + 1, + ISCSI_UEVENT_DESTROY_SESSION = UEVENT_BASE + 2, + ISCSI_UEVENT_CREATE_CONN = UEVENT_BASE + 3, + ISCSI_UEVENT_DESTROY_CONN = UEVENT_BASE + 4, + ISCSI_UEVENT_BIND_CONN = UEVENT_BASE + 5, + ISCSI_UEVENT_SET_PARAM = UEVENT_BASE + 6, + ISCSI_UEVENT_START_CONN = UEVENT_BASE + 7, + ISCSI_UEVENT_STOP_CONN = UEVENT_BASE + 8, + ISCSI_UEVENT_SEND_PDU = UEVENT_BASE + 9, + ISCSI_UEVENT_GET_STATS = UEVENT_BASE + 10, + ISCSI_UEVENT_GET_PARAM = UEVENT_BASE + 11, + + /* up events */ + ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, + ISCSI_KEVENT_CONN_ERROR = KEVENT_BASE + 2, + ISCSI_KEVENT_IF_ERROR = KEVENT_BASE + 3, +}; + +struct iscsi_uevent { + uint32_t type; /* k/u events type */ + uint32_t iferror; /* carries interface or resource errors */ + uint64_t transport_handle; + + union { + /* messages u -> k */ + struct msg_create_session { + uint32_t initial_cmdsn; + } c_session; + struct msg_destroy_session { + uint64_t session_handle; + uint32_t sid; + } d_session; + struct msg_create_conn { + uint64_t session_handle; + uint32_t cid; + uint32_t sid; + } c_conn; + struct msg_bind_conn { + uint64_t session_handle; + uint64_t conn_handle; + uint32_t transport_fd; + uint32_t is_leading; + } b_conn; + struct msg_destroy_conn { + uint64_t conn_handle; + uint32_t cid; + } d_conn; + struct msg_send_pdu { + uint32_t hdr_size; + uint32_t data_size; + uint64_t conn_handle; + } send_pdu; + struct msg_set_param { + uint64_t conn_handle; + uint32_t param; /* enum iscsi_param */ + uint32_t value; + } set_param; + struct msg_start_conn { + uint64_t conn_handle; + } start_conn; + struct msg_stop_conn { + uint64_t conn_handle; + uint32_t flag; + } stop_conn; + struct msg_get_stats { + uint64_t conn_handle; + } get_stats; + } u; + union { + /* messages k -> u */ + uint64_t handle; + int retcode; + struct msg_create_session_ret { + uint64_t session_handle; + uint32_t sid; + } c_session_ret; + struct msg_recv_req { + uint64_t recv_handle; + uint64_t conn_handle; + } recv_req; + struct msg_conn_error { + uint64_t conn_handle; + uint32_t error; /* enum iscsi_err */ + } connerror; + } r; +} __attribute__ ((aligned (sizeof(uint64_t)))); + +/* + * Common error codes + */ +enum iscsi_err { + ISCSI_OK = 0, + + ISCSI_ERR_DATASN = ISCSI_ERR_BASE + 1, + ISCSI_ERR_DATA_OFFSET = ISCSI_ERR_BASE + 2, + ISCSI_ERR_MAX_CMDSN = ISCSI_ERR_BASE + 3, + ISCSI_ERR_EXP_CMDSN = ISCSI_ERR_BASE + 4, + ISCSI_ERR_BAD_OPCODE = ISCSI_ERR_BASE + 5, + ISCSI_ERR_DATALEN = ISCSI_ERR_BASE + 6, + ISCSI_ERR_AHSLEN = ISCSI_ERR_BASE + 7, + ISCSI_ERR_PROTO = ISCSI_ERR_BASE + 8, + ISCSI_ERR_LUN = ISCSI_ERR_BASE + 9, + ISCSI_ERR_BAD_ITT = ISCSI_ERR_BASE + 10, + ISCSI_ERR_CONN_FAILED = ISCSI_ERR_BASE + 11, + ISCSI_ERR_R2TSN = ISCSI_ERR_BASE + 12, + ISCSI_ERR_SESSION_FAILED = ISCSI_ERR_BASE + 13, + ISCSI_ERR_HDR_DGST = ISCSI_ERR_BASE + 14, + ISCSI_ERR_DATA_DGST = ISCSI_ERR_BASE + 15, + ISCSI_ERR_PARAM_NOT_FOUND = ISCSI_ERR_BASE + 16 +}; + +/* + * iSCSI Parameters (RFC3720) + */ +enum iscsi_param { + ISCSI_PARAM_MAX_RECV_DLENGTH = 0, + ISCSI_PARAM_MAX_XMIT_DLENGTH = 1, + ISCSI_PARAM_HDRDGST_EN = 2, + ISCSI_PARAM_DATADGST_EN = 3, + ISCSI_PARAM_INITIAL_R2T_EN = 4, + ISCSI_PARAM_MAX_R2T = 5, + ISCSI_PARAM_IMM_DATA_EN = 6, + ISCSI_PARAM_FIRST_BURST = 7, + ISCSI_PARAM_MAX_BURST = 8, + ISCSI_PARAM_PDU_INORDER_EN = 9, + ISCSI_PARAM_DATASEQ_INORDER_EN = 10, + ISCSI_PARAM_ERL = 11, + ISCSI_PARAM_IFMARKER_EN = 12, + ISCSI_PARAM_OFMARKER_EN = 13, +}; +#define ISCSI_PARAM_MAX 14 + +typedef uint64_t iscsi_sessionh_t; /* iSCSI Data-Path session handle */ +typedef uint64_t iscsi_connh_t; /* iSCSI Data-Path connection handle */ + +#define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) +#define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) +#define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long)) + +/* + * These flags presents iSCSI Data-Path capabilities. + */ +#define CAP_RECOVERY_L0 0x1 +#define CAP_RECOVERY_L1 0x2 +#define CAP_RECOVERY_L2 0x4 +#define CAP_MULTI_R2T 0x8 +#define CAP_HDRDGST 0x10 +#define CAP_DATADGST 0x20 +#define CAP_MULTI_CONN 0x40 +#define CAP_TEXT_NEGO 0x80 +#define CAP_MARKERS 0x100 + +/* + * These flags describes reason of stop_conn() call + */ +#define STOP_CONN_TERM 0x1 +#define STOP_CONN_SUSPEND 0x2 +#define STOP_CONN_RECOVER 0x3 + +#define ISCSI_STATS_CUSTOM_MAX 32 +#define ISCSI_STATS_CUSTOM_DESC_MAX 64 +struct iscsi_stats_custom { + char desc[ISCSI_STATS_CUSTOM_DESC_MAX]; + uint64_t value; +}; + +/* + * struct iscsi_stats - iSCSI Statistics (iSCSI MIB) + * + * Note: this structure contains counters collected on per-connection basis. + */ +struct iscsi_stats { + /* octets */ + uint64_t txdata_octets; + uint64_t rxdata_octets; + + /* xmit pdus */ + uint32_t noptx_pdus; + uint32_t scsicmd_pdus; + uint32_t tmfcmd_pdus; + uint32_t login_pdus; + uint32_t text_pdus; + uint32_t dataout_pdus; + uint32_t logout_pdus; + uint32_t snack_pdus; + + /* recv pdus */ + uint32_t noprx_pdus; + uint32_t scsirsp_pdus; + uint32_t tmfrsp_pdus; + uint32_t textrsp_pdus; + uint32_t datain_pdus; + uint32_t logoutrsp_pdus; + uint32_t r2t_pdus; + uint32_t async_pdus; + uint32_t rjt_pdus; + + /* errors */ + uint32_t digest_err; + uint32_t timeout_err; + + /* + * iSCSI Custom Statistics support, i.e. Transport could + * extend existing MIB statistics with its own specific statistics + * up to ISCSI_STATS_CUSTOM_MAX + */ + uint32_t custom_length; + struct iscsi_stats_custom custom[0] + __attribute__ ((aligned (sizeof(uint64_t)))); +}; + +#endif diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h new file mode 100644 index 000000000000..6c08551c79f5 --- /dev/null +++ b/include/scsi/iscsi_proto.h @@ -0,0 +1,566 @@ +/* + * RFC 3720 (iSCSI) protocol data types + * + * Copyright (C) 2005 Dmitry Yusupov + * Copyright (C) 2005 Alex Aizman + * maintained by open-iscsi@googlegroups.com + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * See the file COPYING included with this distribution for more details. + */ + +#ifndef ISCSI_PROTO_H +#define ISCSI_PROTO_H + +#define ISCSI_VERSION_STR "0.3" +#define ISCSI_DATE_STR "22-Apr-2005" +#define ISCSI_DRAFT20_VERSION 0x00 + +/* default iSCSI listen port for incoming connections */ +#define ISCSI_LISTEN_PORT 3260 + +/* Padding word length */ +#define PAD_WORD_LEN 4 + +/* + * useful common(control and data pathes) macro + */ +#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2])) +#define hton24(p, v) { \ + p[0] = (((v) >> 16) & 0xFF); \ + p[1] = (((v) >> 8) & 0xFF); \ + p[2] = ((v) & 0xFF); \ +} +#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;} + +/* + * iSCSI Template Message Header + */ +struct iscsi_hdr { + uint8_t opcode; + uint8_t flags; /* Final bit */ + uint8_t rsvd2[2]; + uint8_t hlength; /* AHSs total length */ + uint8_t dlength[3]; /* Data length */ + uint8_t lun[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 ttt; /* Target Task Tag */ + __be32 statsn; + __be32 exp_statsn; + uint8_t other[16]; +}; + +/************************* RFC 3720 Begin *****************************/ + +#define ISCSI_RESERVED_TAG 0xffffffff + +/* Opcode encoding bits */ +#define ISCSI_OP_RETRY 0x80 +#define ISCSI_OP_IMMEDIATE 0x40 +#define ISCSI_OPCODE_MASK 0x3F + +/* Initiator Opcode values */ +#define ISCSI_OP_NOOP_OUT 0x00 +#define ISCSI_OP_SCSI_CMD 0x01 +#define ISCSI_OP_SCSI_TMFUNC 0x02 +#define ISCSI_OP_LOGIN 0x03 +#define ISCSI_OP_TEXT 0x04 +#define ISCSI_OP_SCSI_DATA_OUT 0x05 +#define ISCSI_OP_LOGOUT 0x06 +#define ISCSI_OP_SNACK 0x10 + +/* Target Opcode values */ +#define ISCSI_OP_NOOP_IN 0x20 +#define ISCSI_OP_SCSI_CMD_RSP 0x21 +#define ISCSI_OP_SCSI_TMFUNC_RSP 0x22 +#define ISCSI_OP_LOGIN_RSP 0x23 +#define ISCSI_OP_TEXT_RSP 0x24 +#define ISCSI_OP_SCSI_DATA_IN 0x25 +#define ISCSI_OP_LOGOUT_RSP 0x26 +#define ISCSI_OP_R2T 0x31 +#define ISCSI_OP_ASYNC_EVENT 0x32 +#define ISCSI_OP_REJECT 0x3f + +/* iSCSI PDU Header */ +struct iscsi_cmd { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2; + uint8_t cmdrn; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 data_length; + __be32 cmdsn; + __be32 exp_statsn; + uint8_t cdb[16]; /* SCSI Command Block */ + /* Additional Data (Command Dependent) */ +}; + +/* Command PDU flags */ +#define ISCSI_FLAG_CMD_FINAL 0x80 +#define ISCSI_FLAG_CMD_READ 0x40 +#define ISCSI_FLAG_CMD_WRITE 0x20 +#define ISCSI_FLAG_CMD_ATTR_MASK 0x07 /* 3 bits */ + +/* SCSI Command Attribute values */ +#define ISCSI_ATTR_UNTAGGED 0 +#define ISCSI_ATTR_SIMPLE 1 +#define ISCSI_ATTR_ORDERED 2 +#define ISCSI_ATTR_HEAD_OF_QUEUE 3 +#define ISCSI_ATTR_ACA 4 + +/* SCSI Response Header */ +struct iscsi_cmd_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t response; + uint8_t cmd_status; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t rsvd[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 rsvd1; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + __be32 exp_datasn; + __be32 bi_residual_count; + __be32 residual_count; + /* Response or Sense Data (optional) */ +}; + +/* Command Response PDU flags */ +#define ISCSI_FLAG_CMD_BIDI_OVERFLOW 0x10 +#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW 0x08 +#define ISCSI_FLAG_CMD_OVERFLOW 0x04 +#define ISCSI_FLAG_CMD_UNDERFLOW 0x02 + +/* iSCSI Status values. Valid if Rsp Selector bit is not set */ +#define ISCSI_STATUS_CMD_COMPLETED 0 +#define ISCSI_STATUS_TARGET_FAILURE 1 +#define ISCSI_STATUS_SUBSYS_FAILURE 2 + +/* Asynchronous Event Header */ +struct iscsi_async { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2[2]; + uint8_t rsvd3; + uint8_t dlength[3]; + uint8_t lun[8]; + uint8_t rsvd4[8]; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + uint8_t async_event; + uint8_t async_vcode; + __be16 param1; + __be16 param2; + __be16 param3; + uint8_t rsvd5[4]; +}; + +/* iSCSI Event Codes */ +#define ISCSI_ASYNC_MSG_SCSI_EVENT 0 +#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT 1 +#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION 2 +#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS 3 +#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION 4 +#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC 255 + +/* NOP-Out Message */ +struct iscsi_nopout { + uint8_t opcode; + uint8_t flags; + __be16 rsvd2; + uint8_t rsvd3; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 ttt; /* Target Transfer Tag */ + __be32 cmdsn; + __be32 exp_statsn; + uint8_t rsvd4[16]; +}; + +/* NOP-In Message */ +struct iscsi_nopin { + uint8_t opcode; + uint8_t flags; + __be16 rsvd2; + uint8_t rsvd3; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 ttt; /* Target Transfer Tag */ + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + uint8_t rsvd4[12]; +}; + +/* SCSI Task Management Message Header */ +struct iscsi_tm { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd1[2]; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 rtt; /* Reference Task Tag */ + __be32 cmdsn; + __be32 exp_statsn; + __be32 refcmdsn; + __be32 exp_datasn; + uint8_t rsvd2[8]; +}; + +#define ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK 0x7F + +/* Function values */ +#define ISCSI_TM_FUNC_ABORT_TASK 1 +#define ISCSI_TM_FUNC_ABORT_TASK_SET 2 +#define ISCSI_TM_FUNC_CLEAR_ACA 3 +#define ISCSI_TM_FUNC_CLEAR_TASK_SET 4 +#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET 5 +#define ISCSI_TM_FUNC_TARGET_WARM_RESET 6 +#define ISCSI_TM_FUNC_TARGET_COLD_RESET 7 +#define ISCSI_TM_FUNC_TASK_REASSIGN 8 + +/* SCSI Task Management Response Header */ +struct iscsi_tm_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t response; /* see Response values below */ + uint8_t qualifier; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t rsvd2[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 rtt; /* Reference Task Tag */ + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + uint8_t rsvd3[12]; +}; + +/* Response values */ +#define SCSI_TCP_TM_RESP_COMPLETE 0x00 +#define SCSI_TCP_TM_RESP_NO_TASK 0x01 +#define SCSI_TCP_TM_RESP_NO_LUN 0x02 +#define SCSI_TCP_TM_RESP_TASK_ALLEGIANT 0x03 +#define SCSI_TCP_TM_RESP_NO_FAILOVER 0x04 +#define SCSI_TCP_TM_RESP_NOT_SUPPORTED 0x05 +#define SCSI_TCP_TM_RESP_AUTH_FAILED 0x06 +#define SCSI_TCP_TM_RESP_REJECTED 0xff + +/* Ready To Transfer Header */ +struct iscsi_r2t_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2[2]; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 ttt; /* Target Transfer Tag */ + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + __be32 r2tsn; + __be32 data_offset; + __be32 data_length; +}; + +/* SCSI Data Hdr */ +struct iscsi_data { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2[2]; + uint8_t rsvd3; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; + __be32 ttt; + __be32 rsvd4; + __be32 exp_statsn; + __be32 rsvd5; + __be32 datasn; + __be32 offset; + __be32 rsvd6; + /* Payload */ +}; + +/* SCSI Data Response Hdr */ +struct iscsi_data_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2; + uint8_t cmd_status; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t lun[8]; + __be32 itt; + __be32 ttt; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + __be32 datasn; + __be32 offset; + __be32 residual_count; +}; + +/* Data Response PDU flags */ +#define ISCSI_FLAG_DATA_ACK 0x40 +#define ISCSI_FLAG_DATA_OVERFLOW 0x04 +#define ISCSI_FLAG_DATA_UNDERFLOW 0x02 +#define ISCSI_FLAG_DATA_STATUS 0x01 + +/* Text Header */ +struct iscsi_text { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2[2]; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t rsvd4[8]; + __be32 itt; + __be32 ttt; + __be32 cmdsn; + __be32 exp_statsn; + uint8_t rsvd5[16]; + /* Text - key=value pairs */ +}; + +#define ISCSI_FLAG_TEXT_CONTINUE 0x40 + +/* Text Response Header */ +struct iscsi_text_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2[2]; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t rsvd4[8]; + __be32 itt; + __be32 ttt; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + uint8_t rsvd5[12]; + /* Text Response - key:value pairs */ +}; + +/* Login Header */ +struct iscsi_login { + uint8_t opcode; + uint8_t flags; + uint8_t max_version; /* Max. version supported */ + uint8_t min_version; /* Min. version supported */ + uint8_t hlength; + uint8_t dlength[3]; + uint8_t isid[6]; /* Initiator Session ID */ + __be16 tsih; /* Target Session Handle */ + __be32 itt; /* Initiator Task Tag */ + __be16 cid; + __be16 rsvd3; + __be32 cmdsn; + __be32 exp_statsn; + uint8_t rsvd5[16]; +}; + +/* Login PDU flags */ +#define ISCSI_FLAG_LOGIN_TRANSIT 0x80 +#define ISCSI_FLAG_LOGIN_CONTINUE 0x40 +#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK 0x0C /* 2 bits */ +#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK 0x03 /* 2 bits */ + +#define ISCSI_LOGIN_CURRENT_STAGE(flags) \ + ((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2) +#define ISCSI_LOGIN_NEXT_STAGE(flags) \ + (flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK) + +/* Login Response Header */ +struct iscsi_login_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t max_version; /* Max. version supported */ + uint8_t active_version; /* Active version */ + uint8_t hlength; + uint8_t dlength[3]; + uint8_t isid[6]; /* Initiator Session ID */ + __be16 tsih; /* Target Session Handle */ + __be32 itt; /* Initiator Task Tag */ + __be32 rsvd3; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + uint8_t status_class; /* see Login RSP ststus classes below */ + uint8_t status_detail; /* see Login RSP Status details below */ + uint8_t rsvd4[10]; +}; + +/* Login stage (phase) codes for CSG, NSG */ +#define ISCSI_INITIAL_LOGIN_STAGE -1 +#define ISCSI_SECURITY_NEGOTIATION_STAGE 0 +#define ISCSI_OP_PARMS_NEGOTIATION_STAGE 1 +#define ISCSI_FULL_FEATURE_PHASE 3 + +/* Login Status response classes */ +#define ISCSI_STATUS_CLS_SUCCESS 0x00 +#define ISCSI_STATUS_CLS_REDIRECT 0x01 +#define ISCSI_STATUS_CLS_INITIATOR_ERR 0x02 +#define ISCSI_STATUS_CLS_TARGET_ERR 0x03 + +/* Login Status response detail codes */ +/* Class-0 (Success) */ +#define ISCSI_LOGIN_STATUS_ACCEPT 0x00 + +/* Class-1 (Redirection) */ +#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP 0x01 +#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM 0x02 + +/* Class-2 (Initiator Error) */ +#define ISCSI_LOGIN_STATUS_INIT_ERR 0x00 +#define ISCSI_LOGIN_STATUS_AUTH_FAILED 0x01 +#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN 0x02 +#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND 0x03 +#define ISCSI_LOGIN_STATUS_TGT_REMOVED 0x04 +#define ISCSI_LOGIN_STATUS_NO_VERSION 0x05 +#define ISCSI_LOGIN_STATUS_ISID_ERROR 0x06 +#define ISCSI_LOGIN_STATUS_MISSING_FIELDS 0x07 +#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED 0x08 +#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE 0x09 +#define ISCSI_LOGIN_STATUS_NO_SESSION 0x0a +#define ISCSI_LOGIN_STATUS_INVALID_REQUEST 0x0b + +/* Class-3 (Target Error) */ +#define ISCSI_LOGIN_STATUS_TARGET_ERROR 0x00 +#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE 0x01 +#define ISCSI_LOGIN_STATUS_NO_RESOURCES 0x02 + +/* Logout Header */ +struct iscsi_logout { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd1[2]; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t rsvd2[8]; + __be32 itt; /* Initiator Task Tag */ + __be16 cid; + uint8_t rsvd3[2]; + __be32 cmdsn; + __be32 exp_statsn; + uint8_t rsvd4[16]; +}; + +/* Logout PDU flags */ +#define ISCSI_FLAG_LOGOUT_REASON_MASK 0x7F + +/* logout reason_code values */ + +#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0 +#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1 +#define ISCSI_LOGOUT_REASON_RECOVERY 2 +#define ISCSI_LOGOUT_REASON_AEN_REQUEST 3 + +/* Logout Response Header */ +struct iscsi_logout_rsp { + uint8_t opcode; + uint8_t flags; + uint8_t response; /* see Logout response values below */ + uint8_t rsvd2; + uint8_t hlength; + uint8_t dlength[3]; + uint8_t rsvd3[8]; + __be32 itt; /* Initiator Task Tag */ + __be32 rsvd4; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + __be32 rsvd5; + __be16 t2wait; + __be16 t2retain; + __be32 rsvd6; +}; + +/* logout response status values */ + +#define ISCSI_LOGOUT_SUCCESS 0 +#define ISCSI_LOGOUT_CID_NOT_FOUND 1 +#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED 2 +#define ISCSI_LOGOUT_CLEANUP_FAILED 3 + +/* SNACK Header */ +struct iscsi_snack { + uint8_t opcode; + uint8_t flags; + uint8_t rsvd2[14]; + __be32 itt; + __be32 begrun; + __be32 runlength; + __be32 exp_statsn; + __be32 rsvd3; + __be32 exp_datasn; + uint8_t rsvd6[8]; +}; + +/* SNACK PDU flags */ +#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */ + +/* Reject Message Header */ +struct iscsi_reject { + uint8_t opcode; + uint8_t flags; + uint8_t reason; + uint8_t rsvd2; + uint8_t rsvd3; + uint8_t dlength[3]; + uint8_t rsvd4[16]; + __be32 statsn; + __be32 exp_cmdsn; + __be32 max_cmdsn; + __be32 datasn; + uint8_t rsvd5[8]; + /* Text - Rejected hdr */ +}; + +/* Reason for Reject */ +#define CMD_BEFORE_LOGIN 1 +#define DATA_DIGEST_ERROR 2 +#define DATA_SNACK_REJECT 3 +#define ISCSI_PROTOCOL_ERROR 4 +#define CMD_NOT_SUPPORTED 5 +#define IMM_CMD_REJECT 6 +#define TASK_IN_PROGRESS 7 +#define INVALID_SNACK 8 +#define BOOKMARK_REJECTED 9 +#define BOOKMARK_NO_RESOURCES 10 +#define NEGOTIATION_RESET 11 + +/* Max. number of Key=Value pairs in a text message */ +#define MAX_KEY_VALUE_PAIRS 8192 + +/* maximum length for text keys/values */ +#define KEY_MAXLEN 64 +#define VALUE_MAXLEN 255 +#define TARGET_NAME_MAXLEN VALUE_MAXLEN + +#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 + +/************************* RFC 3720 End *****************************/ + +#endif /* ISCSI_PROTO_H */ diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 1b26a6c0aa2a..f25041c386ec 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -1,8 +1,10 @@ -/* +/* * iSCSI transport class definitions * * Copyright (C) IBM Corporation, 2004 - * Copyright (C) Mike Christie, 2004 + * Copyright (C) Mike Christie, 2004 - 2005 + * Copyright (C) Dmitry Yusupov, 2004 - 2005 + * Copyright (C) Alex Aizman, 2004 - 2005 * * 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 @@ -21,158 +23,64 @@ #ifndef SCSI_TRANSPORT_ISCSI_H #define SCSI_TRANSPORT_ISCSI_H -#include -#include -#include - -struct scsi_transport_template; +#include -struct iscsi_class_session { - uint8_t isid[6]; - uint16_t tsih; - int header_digest; /* 1 CRC32, 0 None */ - int data_digest; /* 1 CRC32, 0 None */ - uint16_t tpgt; - union { - struct in6_addr sin6_addr; - struct in_addr sin_addr; - } u; - sa_family_t addr_type; /* must be AF_INET or AF_INET6 */ - uint16_t port; /* must be in network byte order */ - int initial_r2t; /* 1 Yes, 0 No */ - int immediate_data; /* 1 Yes, 0 No */ - uint32_t max_recv_data_segment_len; - uint32_t max_burst_len; - uint32_t first_burst_len; - uint16_t def_time2wait; - uint16_t def_time2retain; - uint16_t max_outstanding_r2t; - int data_pdu_in_order; /* 1 Yes, 0 No */ - int data_sequence_in_order; /* 1 Yes, 0 No */ - int erl; +/** + * struct iscsi_transport - iSCSI Transport template + * + * @name: transport name + * @caps: iSCSI Data-Path capabilities + * @create_session: create new iSCSI session object + * @destroy_session: destroy existing iSCSI session object + * @create_conn: create new iSCSI connection + * @bind_conn: associate this connection with existing iSCSI session + * and specified transport descriptor + * @destroy_conn: destroy inactive iSCSI connection + * @set_param: set iSCSI Data-Path operational parameter + * @start_conn: set connection to be operational + * @stop_conn: suspend/recover/terminate connection + * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text. + * + * Template API provided by iSCSI Transport + */ +struct iscsi_transport { + struct module *owner; + char *name; + unsigned int caps; + struct scsi_host_template *host_template; + int hostdata_size; + int max_lun; + unsigned int max_conn; + unsigned int max_cmd_len; + iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn, + struct Scsi_Host *shost); + void (*destroy_session) (iscsi_sessionh_t session); + iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid); + int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn, + uint32_t transport_fd, int is_leading); + int (*start_conn) (iscsi_connh_t conn); + void (*stop_conn) (iscsi_connh_t conn, int flag); + void (*destroy_conn) (iscsi_connh_t conn); + int (*set_param) (iscsi_connh_t conn, enum iscsi_param param, + uint32_t value); + int (*get_param) (iscsi_connh_t conn, enum iscsi_param param, + uint32_t *value); + int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size); + void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats); }; /* - * accessor macros + * transport registration upcalls */ -#define iscsi_isid(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->isid) -#define iscsi_tsih(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->tsih) -#define iscsi_header_digest(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->header_digest) -#define iscsi_data_digest(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->data_digest) -#define iscsi_port(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->port) -#define iscsi_addr_type(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->addr_type) -#define iscsi_sin_addr(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->u.sin_addr) -#define iscsi_sin6_addr(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->u.sin6_addr) -#define iscsi_tpgt(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->tpgt) -#define iscsi_initial_r2t(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->initial_r2t) -#define iscsi_immediate_data(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->immediate_data) -#define iscsi_max_recv_data_segment_len(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->max_recv_data_segment_len) -#define iscsi_max_burst_len(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->max_burst_len) -#define iscsi_first_burst_len(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->first_burst_len) -#define iscsi_def_time2wait(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->def_time2wait) -#define iscsi_def_time2retain(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->def_time2retain) -#define iscsi_max_outstanding_r2t(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->max_outstanding_r2t) -#define iscsi_data_pdu_in_order(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->data_pdu_in_order) -#define iscsi_data_sequence_in_order(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->data_sequence_in_order) -#define iscsi_erl(x) \ - (((struct iscsi_class_session *)&(x)->starget_data)->erl) +extern int iscsi_register_transport(struct iscsi_transport *tt); +extern int iscsi_unregister_transport(struct iscsi_transport *tt); /* - * The functions by which the transport class and the driver communicate + * control plane upcalls */ -struct iscsi_function_template { - /* - * target attrs - */ - void (*get_isid)(struct scsi_target *); - void (*get_tsih)(struct scsi_target *); - void (*get_header_digest)(struct scsi_target *); - void (*get_data_digest)(struct scsi_target *); - void (*get_port)(struct scsi_target *); - void (*get_tpgt)(struct scsi_target *); - /* - * In get_ip_address the lld must set the address and - * the address type - */ - void (*get_ip_address)(struct scsi_target *); - /* - * The lld should snprintf the name or alias to the buffer - */ - ssize_t (*get_target_name)(struct scsi_target *, char *, ssize_t); - ssize_t (*get_target_alias)(struct scsi_target *, char *, ssize_t); - void (*get_initial_r2t)(struct scsi_target *); - void (*get_immediate_data)(struct scsi_target *); - void (*get_max_recv_data_segment_len)(struct scsi_target *); - void (*get_max_burst_len)(struct scsi_target *); - void (*get_first_burst_len)(struct scsi_target *); - void (*get_def_time2wait)(struct scsi_target *); - void (*get_def_time2retain)(struct scsi_target *); - void (*get_max_outstanding_r2t)(struct scsi_target *); - void (*get_data_pdu_in_order)(struct scsi_target *); - void (*get_data_sequence_in_order)(struct scsi_target *); - void (*get_erl)(struct scsi_target *); - - /* - * host atts - */ - - /* - * The lld should snprintf the name or alias to the buffer - */ - ssize_t (*get_initiator_alias)(struct Scsi_Host *, char *, ssize_t); - ssize_t (*get_initiator_name)(struct Scsi_Host *, char *, ssize_t); - /* - * The driver sets these to tell the transport class it - * wants the attributes displayed in sysfs. If the show_ flag - * is not set, the attribute will be private to the transport - * class. We could probably just test if a get_ fn was set - * since we only use the values for sysfs but this is how - * fc does it too. - */ - unsigned long show_isid:1; - unsigned long show_tsih:1; - unsigned long show_header_digest:1; - unsigned long show_data_digest:1; - unsigned long show_port:1; - unsigned long show_tpgt:1; - unsigned long show_ip_address:1; - unsigned long show_target_name:1; - unsigned long show_target_alias:1; - unsigned long show_initial_r2t:1; - unsigned long show_immediate_data:1; - unsigned long show_max_recv_data_segment_len:1; - unsigned long show_max_burst_len:1; - unsigned long show_first_burst_len:1; - unsigned long show_def_time2wait:1; - unsigned long show_def_time2retain:1; - unsigned long show_max_outstanding_r2t:1; - unsigned long show_data_pdu_in_order:1; - unsigned long show_data_sequence_in_order:1; - unsigned long show_erl:1; - unsigned long show_initiator_name:1; - unsigned long show_initiator_alias:1; -}; - -struct scsi_transport_template *iscsi_attach_transport(struct iscsi_function_template *); -void iscsi_release_transport(struct scsi_transport_template *); +extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error); +extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size); #endif -- cgit v1.2.3 From baebc497b43a69d7280af226e08214c527220d45 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 12 Sep 2005 21:01:38 -0500 Subject: [SCSI] iscsi: update some iscsi proto defs From: michaelc@cs.wisc.edu Cleanup some iscsi_proto defs, add some missing values, and fix some defs. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2 +- include/scsi/iscsi_proto.h | 45 +++++++++++++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index bb0a5039d334..baacf836083e 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -751,7 +751,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) (void*)&mtask, sizeof(void*)); conn->tmabort_state = ((struct iscsi_tm_rsp *)hdr)-> - response == SCSI_TCP_TM_RESP_COMPLETE ? + response == ISCSI_TMF_RSP_COMPLETE ? TMABORT_SUCCESS:TMABORT_FAILED; /* unblock eh_abort() */ wake_up(&conn->ehwait); diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 6c08551c79f5..8d3190480441 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -56,7 +56,8 @@ struct iscsi_hdr { __be32 ttt; /* Target Task Tag */ __be32 statsn; __be32 exp_statsn; - uint8_t other[16]; + __be32 max_statsn; + uint8_t other[12]; }; /************************* RFC 3720 Begin *****************************/ @@ -78,6 +79,11 @@ struct iscsi_hdr { #define ISCSI_OP_LOGOUT 0x06 #define ISCSI_OP_SNACK 0x10 +#define ISCSI_OP_VENDOR1_CMD 0x1c +#define ISCSI_OP_VENDOR2_CMD 0x1d +#define ISCSI_OP_VENDOR3_CMD 0x1e +#define ISCSI_OP_VENDOR4_CMD 0x1f + /* Target Opcode values */ #define ISCSI_OP_NOOP_IN 0x20 #define ISCSI_OP_SCSI_CMD_RSP 0x21 @@ -90,12 +96,20 @@ struct iscsi_hdr { #define ISCSI_OP_ASYNC_EVENT 0x32 #define ISCSI_OP_REJECT 0x3f +struct iscsi_ahs_hdr { + __be16 ahslength; + uint8_t ahstype; + uint8_t ahspec[5]; +}; + +#define ISCSI_AHSTYPE_CDB 1 +#define ISCSI_AHSTYPE_RLENGTH 2 + /* iSCSI PDU Header */ struct iscsi_cmd { uint8_t opcode; uint8_t flags; - uint8_t rsvd2; - uint8_t cmdrn; + __be16 rsvd2; uint8_t hlength; uint8_t dlength[3]; uint8_t lun[8]; @@ -120,6 +134,13 @@ struct iscsi_cmd { #define ISCSI_ATTR_HEAD_OF_QUEUE 3 #define ISCSI_ATTR_ACA 4 +struct iscsi_rlength_ahdr { + __be16 ahslength; + uint8_t ahstype; + uint8_t reserved; + __be32 read_length; +}; + /* SCSI Response Header */ struct iscsi_cmd_rsp { uint8_t opcode; @@ -227,7 +248,7 @@ struct iscsi_tm { uint8_t rsvd2[8]; }; -#define ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK 0x7F +#define ISCSI_FLAG_TM_FUNC_MASK 0x7F /* Function values */ #define ISCSI_TM_FUNC_ABORT_TASK 1 @@ -257,14 +278,14 @@ struct iscsi_tm_rsp { }; /* Response values */ -#define SCSI_TCP_TM_RESP_COMPLETE 0x00 -#define SCSI_TCP_TM_RESP_NO_TASK 0x01 -#define SCSI_TCP_TM_RESP_NO_LUN 0x02 -#define SCSI_TCP_TM_RESP_TASK_ALLEGIANT 0x03 -#define SCSI_TCP_TM_RESP_NO_FAILOVER 0x04 -#define SCSI_TCP_TM_RESP_NOT_SUPPORTED 0x05 -#define SCSI_TCP_TM_RESP_AUTH_FAILED 0x06 -#define SCSI_TCP_TM_RESP_REJECTED 0xff +#define ISCSI_TMF_RSP_COMPLETE 0x00 +#define ISCSI_TMF_RSP_NO_TASK 0x01 +#define ISCSI_TMF_RSP_NO_LUN 0x02 +#define ISCSI_TMF_RSP_TASK_ALLEGIANT 0x03 +#define ISCSI_TMF_RSP_NO_FAILOVER 0x04 +#define ISCSI_TMF_RSP_NOT_SUPPORTED 0x05 +#define ISCSI_TMF_RSP_AUTH_FAILED 0x06 +#define ISCSI_TMF_RSP_REJECTED 0xff /* Ready To Transfer Header */ struct iscsi_r2t_rsp { -- cgit v1.2.3 From fa0a6957aa7d02addb08a231c8e7c77c2b8fcd20 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 12 Sep 2005 21:01:57 -0500 Subject: [SCSI] iscsi: rename some proto defs From: hare@suse.de for a proper alignment between open-iscsi and iscsitarget the definitions in include/iscsi_proto.h do not match exactly. With this patch it's possible to have iscsitarget use 'include/iscsi_proto.h' instead of its own iscsi_hdr.h. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- include/scsi/iscsi_proto.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 8d3190480441..4feda05fdf25 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -548,9 +548,11 @@ struct iscsi_reject { uint8_t flags; uint8_t reason; uint8_t rsvd2; - uint8_t rsvd3; + uint8_t hlength; uint8_t dlength[3]; - uint8_t rsvd4[16]; + uint8_t rsvd3[8]; + __be32 ffffffff; + uint8_t rsvd4[4]; __be32 statsn; __be32 exp_cmdsn; __be32 max_cmdsn; @@ -560,17 +562,17 @@ struct iscsi_reject { }; /* Reason for Reject */ -#define CMD_BEFORE_LOGIN 1 -#define DATA_DIGEST_ERROR 2 -#define DATA_SNACK_REJECT 3 -#define ISCSI_PROTOCOL_ERROR 4 -#define CMD_NOT_SUPPORTED 5 -#define IMM_CMD_REJECT 6 -#define TASK_IN_PROGRESS 7 -#define INVALID_SNACK 8 -#define BOOKMARK_REJECTED 9 -#define BOOKMARK_NO_RESOURCES 10 -#define NEGOTIATION_RESET 11 +#define ISCSI_REASON_CMD_BEFORE_LOGIN 1 +#define ISCSI_REASON_DATA_DIGEST_ERROR 2 +#define ISCSI_REASON_DATA_SNACK_REJECT 3 +#define ISCSI_REASON_PROTOCOL_ERROR 4 +#define ISCSI_REASON_CMD_NOT_SUPPORTED 5 +#define ISCSI_REASON_IMM_CMD_REJECT 6 +#define ISCSI_REASON_TASK_IN_PROGRESS 7 +#define ISCSI_REASON_INVALID_SNACK 8 +#define ISCSI_REASON_BOOKMARK_INVALID 9 +#define ISCSI_REASON_BOOKMARK_NO_RESOURCES 10 +#define ISCSI_REASON_NEGOTIATION_RESET 11 /* Max. number of Key=Value pairs in a text message */ #define MAX_KEY_VALUE_PAIRS 8192 -- cgit v1.2.3 From 878a97cfd7014b01285db09f52f9881ffe4cb608 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Sep 2005 14:44:23 -0700 Subject: [PATCH] swiotlb: support syncing sub-ranges of mappings This patch implements swiotlb_sync_single_range_for_{cpu,device}. This is intended to support an x86_64 implementation of dma_sync_single_range_for_{cpu,device}. Signed-off-by: John W. Linville Signed-off-by: Tony Luck --- include/asm-x86_64/swiotlb.h | 8 ++++++++ lib/swiotlb.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'include') diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h index 36293061f4ed..9b011dd8d19d 100644 --- a/include/asm-x86_64/swiotlb.h +++ b/include/asm-x86_64/swiotlb.h @@ -15,6 +15,14 @@ extern void swiotlb_sync_single_for_cpu(struct device *hwdev, extern void swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir); +extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev, + dma_addr_t dev_addr, + unsigned long offset, + size_t size, int dir); +extern void swiotlb_sync_single_range_for_device(struct device *hwdev, + dma_addr_t dev_addr, + unsigned long offset, + size_t size, int dir); extern void swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, int nelems, int dir); diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 9719a14649e7..566791b3f583 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -622,6 +622,37 @@ swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, swiotlb_sync_single(hwdev, dev_addr, size, dir); } +/* + * Same as above, but for a sub-range of the mapping. + */ +static inline void +swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr, + unsigned long offset, size_t size, int dir) +{ + char *dma_addr = phys_to_virt(dev_addr) + offset; + + if (dir == DMA_NONE) + BUG(); + if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) + sync_single(hwdev, dma_addr, size, dir); + else if (dir == DMA_FROM_DEVICE) + mark_clean(dma_addr, size); +} + +void +swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr, + unsigned long offset, size_t size, int dir) +{ + swiotlb_sync_single_range(hwdev, dev_addr, offset, size, dir); +} + +void +swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr, + unsigned long offset, size_t size, int dir) +{ + swiotlb_sync_single_range(hwdev, dev_addr, offset, size, dir); +} + /* * Map a set of buffers described by scatterlist in streaming mode for DMA. * This is the scatter-gather version of the above swiotlb_map_single @@ -750,6 +781,8 @@ EXPORT_SYMBOL(swiotlb_map_sg); EXPORT_SYMBOL(swiotlb_unmap_sg); EXPORT_SYMBOL(swiotlb_sync_single_for_cpu); EXPORT_SYMBOL(swiotlb_sync_single_for_device); +EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_cpu); +EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device); EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); EXPORT_SYMBOL(swiotlb_sync_sg_for_device); EXPORT_SYMBOL(swiotlb_dma_mapping_error); -- cgit v1.2.3 From 8d15d19e44d2e903d00ae4b70da917ac77921239 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Sep 2005 14:45:52 -0700 Subject: [PATCH] x86_64: implement dma_sync_single_range_for_{cpu,device} Re-implement dma_sync_single_range_for_{cpu,device} for x86_64 using swiotlb_sync_single_range_for_{cpu,device}. Signed-off-by: John W. Linville Signed-off-by: Tony Luck --- include/asm-x86_64/dma-mapping.h | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h index e784fdc524f1..45ca88c875c0 100644 --- a/include/asm-x86_64/dma-mapping.h +++ b/include/asm-x86_64/dma-mapping.h @@ -85,10 +85,33 @@ static inline void dma_sync_single_for_device(struct device *hwdev, flush_write_buffers(); } -#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir) \ - dma_sync_single_for_cpu(dev, dma_handle, size, dir) -#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir) \ - dma_sync_single_for_device(dev, dma_handle, size, dir) +static inline void dma_sync_single_range_for_cpu(struct device *hwdev, + dma_addr_t dma_handle, + unsigned long offset, + size_t size, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + + if (swiotlb) + return swiotlb_sync_single_range_for_cpu(hwdev,dma_handle,offset,size,direction); + + flush_write_buffers(); +} + +static inline void dma_sync_single_range_for_device(struct device *hwdev, + dma_addr_t dma_handle, + unsigned long offset, + size_t size, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + + if (swiotlb) + return swiotlb_sync_single_range_for_device(hwdev,dma_handle,offset,size,direction); + + flush_write_buffers(); +} static inline void dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, -- cgit v1.2.3 From cedc9a478d8c6265879dc3839ef3d4849a709184 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 5 Oct 2005 07:13:30 -0400 Subject: libata: fix ATAPI DMA alignment issues ATAPI needs to be padded to next 4 byte boundary, if misaligned. Original work by me, many fixes from Tejun Heo. --- drivers/scsi/ahci.c | 30 +++++++---- drivers/scsi/libata-core.c | 123 ++++++++++++++++++++++++++++++++++++++------- drivers/scsi/libata-scsi.c | 14 +++++- drivers/scsi/sata_qstor.c | 8 +-- drivers/scsi/sata_sx4.c | 13 +++-- include/linux/libata.h | 27 +++++++++- 6 files changed, 174 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c2c8fa828e24..6e4bb36f8d7c 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -314,8 +314,15 @@ static int ahci_port_start(struct ata_port *ap) return -ENOMEM; memset(pp, 0, sizeof(*pp)); + ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); + if (!ap->pad) { + kfree(pp); + return -ENOMEM; + } + mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { + dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); kfree(pp); return -ENOMEM; } @@ -391,6 +398,7 @@ static void ahci_port_stop(struct ata_port *ap) ap->private_data = NULL; dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, pp->cmd_slot, pp->cmd_slot_dma); + dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); kfree(pp); } @@ -476,23 +484,23 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) static void ahci_fill_sg(struct ata_queued_cmd *qc) { struct ahci_port_priv *pp = qc->ap->private_data; - unsigned int i; + struct scatterlist *sg; + struct ahci_sg *ahci_sg; VPRINTK("ENTER\n"); /* * Next, the S/G list. */ - for (i = 0; i < qc->n_elem; i++) { - u32 sg_len; - dma_addr_t addr; - - addr = sg_dma_address(&qc->sg[i]); - sg_len = sg_dma_len(&qc->sg[i]); - - pp->cmd_tbl_sg[i].addr = cpu_to_le32(addr & 0xffffffff); - pp->cmd_tbl_sg[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); - pp->cmd_tbl_sg[i].flags_size = cpu_to_le32(sg_len - 1); + ahci_sg = pp->cmd_tbl_sg; + ata_for_each_sg(sg, qc) { + dma_addr_t addr = sg_dma_address(sg); + u32 sg_len = sg_dma_len(sg); + + ahci_sg->addr = cpu_to_le32(addr & 0xffffffff); + ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); + ahci_sg->flags_size = cpu_to_le32(sg_len - 1); + ahci_sg++; } } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e5b01997117a..943b44c3c16f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2156,8 +2156,9 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) static void ata_sg_clean(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scatterlist *sg = qc->sg; + struct scatterlist *sg = qc->__sg; int dir = qc->dma_dir; + void *pad_buf = NULL; assert(qc->flags & ATA_QCFLAG_DMAMAP); assert(sg != NULL); @@ -2167,14 +2168,35 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) DPRINTK("unmapping %u sg elements\n", qc->n_elem); - if (qc->flags & ATA_QCFLAG_SG) + /* if we padded the buffer out to 32-bit bound, and data + * xfer direction is from-device, we must copy from the + * pad buffer back into the supplied buffer + */ + if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE)) + pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); + + if (qc->flags & ATA_QCFLAG_SG) { dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); - else + /* restore last sg */ + sg[qc->orig_n_elem - 1].length += qc->pad_len; + if (pad_buf) { + struct scatterlist *psg = &qc->pad_sgent; + void *addr = kmap_atomic(psg->page, KM_IRQ0); + memcpy(addr + psg->offset, pad_buf, qc->pad_len); + kunmap_atomic(psg->page, KM_IRQ0); + } + } else { dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); + /* restore sg */ + sg->length += qc->pad_len; + if (pad_buf) + memcpy(qc->buf_virt + sg->length - qc->pad_len, + pad_buf, qc->pad_len); + } qc->flags &= ~ATA_QCFLAG_DMAMAP; - qc->sg = NULL; + qc->__sg = NULL; } /** @@ -2190,15 +2212,15 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) */ static void ata_fill_sg(struct ata_queued_cmd *qc) { - struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; - unsigned int idx, nelem; + struct scatterlist *sg; + unsigned int idx; - assert(sg != NULL); + assert(qc->__sg != NULL); assert(qc->n_elem > 0); idx = 0; - for (nelem = qc->n_elem; nelem; nelem--,sg++) { + ata_for_each_sg(sg, qc) { u32 addr, offset; u32 sg_len, len; @@ -2289,11 +2311,12 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) qc->flags |= ATA_QCFLAG_SINGLE; memset(&qc->sgent, 0, sizeof(qc->sgent)); - qc->sg = &qc->sgent; + qc->__sg = &qc->sgent; qc->n_elem = 1; + qc->orig_n_elem = 1; qc->buf_virt = buf; - sg = qc->sg; + sg = qc->__sg; sg->page = virt_to_page(buf); sg->offset = (unsigned long) buf & ~PAGE_MASK; sg->length = buflen; @@ -2317,8 +2340,9 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem) { qc->flags |= ATA_QCFLAG_SG; - qc->sg = sg; + qc->__sg = sg; qc->n_elem = n_elem; + qc->orig_n_elem = n_elem; } /** @@ -2338,9 +2362,32 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; int dir = qc->dma_dir; - struct scatterlist *sg = qc->sg; + struct scatterlist *sg = qc->__sg; dma_addr_t dma_address; + /* we must lengthen transfers to end on a 32-bit boundary */ + qc->pad_len = sg->length & 3; + if (qc->pad_len) { + void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); + struct scatterlist *psg = &qc->pad_sgent; + + assert(qc->dev->class == ATA_DEV_ATAPI); + + memset(pad_buf, 0, ATA_DMA_PAD_SZ); + + if (qc->tf.flags & ATA_TFLAG_WRITE) + memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len, + qc->pad_len); + + sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ); + sg_dma_len(psg) = ATA_DMA_PAD_SZ; + /* trim sg */ + sg->length -= qc->pad_len; + + DPRINTK("padding done, sg->length=%u pad_len=%u\n", + sg->length, qc->pad_len); + } + dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, sg->length, dir); if (dma_mapping_error(dma_address)) @@ -2372,12 +2419,47 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) static int ata_sg_setup(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scatterlist *sg = qc->sg; + struct scatterlist *sg = qc->__sg; + struct scatterlist *lsg = &sg[qc->n_elem - 1]; int n_elem, dir; VPRINTK("ENTER, ata%u\n", ap->id); assert(qc->flags & ATA_QCFLAG_SG); + /* we must lengthen transfers to end on a 32-bit boundary */ + qc->pad_len = lsg->length & 3; + if (qc->pad_len) { + void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); + struct scatterlist *psg = &qc->pad_sgent; + unsigned int offset; + + assert(qc->dev->class == ATA_DEV_ATAPI); + + memset(pad_buf, 0, ATA_DMA_PAD_SZ); + + /* + * psg->page/offset are used to copy to-be-written + * data in this function or read data in ata_sg_clean. + */ + offset = lsg->offset + lsg->length - qc->pad_len; + psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT); + psg->offset = offset_in_page(offset); + + if (qc->tf.flags & ATA_TFLAG_WRITE) { + void *addr = kmap_atomic(psg->page, KM_IRQ0); + memcpy(pad_buf, addr + psg->offset, qc->pad_len); + kunmap_atomic(psg->page, KM_IRQ0); + } + + sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ); + sg_dma_len(psg) = ATA_DMA_PAD_SZ; + /* trim last sg */ + lsg->length -= qc->pad_len; + + DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n", + qc->n_elem - 1, lsg->length, qc->pad_len); + } + dir = qc->dma_dir; n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir); if (n_elem < 1) @@ -2655,7 +2737,7 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, static void ata_pio_sector(struct ata_queued_cmd *qc) { int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); - struct scatterlist *sg = qc->sg; + struct scatterlist *sg = qc->__sg; struct ata_port *ap = qc->ap; struct page *page; unsigned int offset; @@ -2705,7 +2787,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) { int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); - struct scatterlist *sg = qc->sg; + struct scatterlist *sg = qc->__sg; struct ata_port *ap = qc->ap; struct page *page; unsigned char *buf; @@ -2738,7 +2820,7 @@ next_sg: return; } - sg = &qc->sg[qc->cursg]; + sg = &qc->__sg[qc->cursg]; page = sg->page; offset = sg->offset + qc->cursg_ofs; @@ -3145,7 +3227,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, qc = ata_qc_new(ap); if (qc) { - qc->sg = NULL; + qc->__sg = NULL; qc->flags = 0; qc->scsicmd = NULL; qc->ap = ap; @@ -3837,6 +3919,12 @@ int ata_port_start (struct ata_port *ap) if (!ap->prd) return -ENOMEM; + ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); + if (!ap->pad) { + dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); + return -ENOMEM; + } + DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma); return 0; @@ -3859,6 +3947,7 @@ void ata_port_stop (struct ata_port *ap) struct device *dev = ap->host_set->dev; dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); + dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); } void ata_host_stop (struct ata_host_set *host_set) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 104fd9a63e73..ee3f1050fb5f 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -150,10 +150,10 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, qc->scsidone = done; if (cmd->use_sg) { - qc->sg = (struct scatterlist *) cmd->request_buffer; + qc->__sg = (struct scatterlist *) cmd->request_buffer; qc->n_elem = cmd->use_sg; } else { - qc->sg = &qc->sgent; + qc->__sg = &qc->sgent; qc->n_elem = 1; } } else { @@ -364,6 +364,16 @@ int ata_scsi_slave_config(struct scsi_device *sdev) */ blk_queue_max_sectors(sdev->request_queue, 2048); } + + /* + * SATA DMA transfers must be multiples of 4 byte, so + * we need to pad ATAPI transfers using an extra sg. + * Decrement max hw segments accordingly. + */ + if (dev->class == ATA_DEV_ATAPI) { + request_queue_t *q = sdev->request_queue; + blk_queue_max_hw_segments(q, q->max_hw_segments - 1); + } } return 0; /* scsi layer doesn't check return value, sigh */ diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index ffcdeb68641c..69a9b1cf6f9c 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -268,16 +268,17 @@ static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) static void qs_fill_sg(struct ata_queued_cmd *qc) { - struct scatterlist *sg = qc->sg; + struct scatterlist *sg; struct ata_port *ap = qc->ap; struct qs_port_priv *pp = ap->private_data; unsigned int nelem; u8 *prd = pp->pkt + QS_CPB_BYTES; - assert(sg != NULL); + assert(qc->__sg != NULL); assert(qc->n_elem > 0); - for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) { + nelem = 0; + ata_for_each_sg(sg, qc) { u64 addr; u32 len; @@ -291,6 +292,7 @@ static void qs_fill_sg(struct ata_queued_cmd *qc) VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem, (unsigned long long)addr, len); + nelem++; } } diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 540a85191172..79fdbbab513e 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -449,14 +449,14 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, static void pdc20621_dma_prep(struct ata_queued_cmd *qc) { - struct scatterlist *sg = qc->sg; + struct scatterlist *sg; struct ata_port *ap = qc->ap; struct pdc_port_priv *pp = ap->private_data; void __iomem *mmio = ap->host_set->mmio_base; struct pdc_host_priv *hpriv = ap->host_set->private_data; void __iomem *dimm_mmio = hpriv->dimm_mmio; unsigned int portno = ap->port_no; - unsigned int i, last, idx, total_len = 0, sgt_len; + unsigned int i, idx, total_len = 0, sgt_len; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; assert(qc->flags & ATA_QCFLAG_DMAMAP); @@ -469,12 +469,11 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) /* * Build S/G table */ - last = qc->n_elem; idx = 0; - for (i = 0; i < last; i++) { - buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); - buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); - total_len += sg_dma_len(&sg[i]); + ata_for_each_sg(sg, qc) { + buf[idx++] = cpu_to_le32(sg_dma_address(sg)); + buf[idx++] = cpu_to_le32(sg_dma_len(sg)); + total_len += sg_dma_len(sg); } buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); sgt_len = idx * 4; diff --git a/include/linux/libata.h b/include/linux/libata.h index ceee1fc42c60..3ab67622ef93 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -154,6 +154,10 @@ enum { ATA_SHIFT_UDMA = 0, ATA_SHIFT_MWDMA = 8, ATA_SHIFT_PIO = 11, + + /* size of buffer to pad xfers ending on unaligned boundaries */ + ATA_DMA_PAD_SZ = 4, + ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, }; enum pio_task_states { @@ -237,9 +241,12 @@ struct ata_queued_cmd { unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned int tag; unsigned int n_elem; + unsigned int orig_n_elem; int dma_dir; + unsigned int pad_len; + unsigned int nsect; unsigned int cursect; @@ -250,9 +257,11 @@ struct ata_queued_cmd { unsigned int cursg_ofs; struct scatterlist sgent; + struct scatterlist pad_sgent; void *buf_virt; - struct scatterlist *sg; + /* DO NOT iterate over __sg manually, use ata_for_each_sg() */ + struct scatterlist *__sg; ata_qc_cb_t complete_fn; @@ -295,6 +304,9 @@ struct ata_port { struct ata_prd *prd; /* our SG list */ dma_addr_t prd_dma; /* and its DMA mapping */ + void *pad; /* array of DMA pad buffers */ + dma_addr_t pad_dma; + struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ u8 ctl; /* cache of ATA control register */ @@ -458,6 +470,19 @@ extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); #endif /* CONFIG_PCI */ +static inline struct scatterlist * +ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) +{ + if (sg == &qc->pad_sgent) + return NULL; + if (++sg - qc->__sg < qc->n_elem) + return sg; + return qc->pad_len ? &qc->pad_sgent : NULL; +} + +#define ata_for_each_sg(sg, qc) \ + for (sg = qc->__sg; sg; sg = ata_qc_next_sg(sg, qc)) + static inline unsigned int ata_tag_valid(unsigned int tag) { return (tag < ATA_MAX_QUEUE) ? 1 : 0; -- cgit v1.2.3 From 972c26bdd6b58e7534473c4f7928584578cf43f4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 18 Oct 2005 22:14:54 -0400 Subject: libata: add ata_sg_is_last() helper, use it in several drivers --- drivers/scsi/pdc_adma.c | 8 ++++---- drivers/scsi/sata_mv.c | 16 +++++++++------- drivers/scsi/sata_sil24.c | 15 ++++++++++----- include/linux/libata.h | 12 ++++++++++++ 4 files changed, 35 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 53b8db4be1a9..c6825da6ae20 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -293,14 +293,14 @@ static void adma_eng_timeout(struct ata_port *ap) static int adma_fill_sg(struct ata_queued_cmd *qc) { - struct scatterlist *sg = qc->sg; + struct scatterlist *sg; struct ata_port *ap = qc->ap; struct adma_port_priv *pp = ap->private_data; u8 *buf = pp->pkt; - int nelem, i = (2 + buf[3]) * 8; + int i = (2 + buf[3]) * 8; u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0); - for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) { + ata_for_each_sg(sg, qc) { u32 addr; u32 len; @@ -312,7 +312,7 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) *(__le32 *)(buf + i) = cpu_to_le32(len); i += 4; - if ((nelem + 1) == qc->n_elem) + if (ata_sg_is_last(sg, qc)) pFLAGS |= pEND; buf[i++] = pFLAGS; buf[i++] = qc->dev->dma_mode & 0xf; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index d457f5673476..be7c378dcd36 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -785,22 +785,24 @@ static void mv_port_stop(struct ata_port *ap) static void mv_fill_sg(struct ata_queued_cmd *qc) { struct mv_port_priv *pp = qc->ap->private_data; - unsigned int i; + unsigned int i = 0; + struct scatterlist *sg; - for (i = 0; i < qc->n_elem; i++) { + ata_for_each_sg(sg, qc) { u32 sg_len; dma_addr_t addr; - addr = sg_dma_address(&qc->sg[i]); - sg_len = sg_dma_len(&qc->sg[i]); + addr = sg_dma_address(sg); + sg_len = sg_dma_len(sg); pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); assert(0 == (sg_len & ~MV_DMA_BOUNDARY)); pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len); - } - if (0 < qc->n_elem) { - pp->sg_tbl[qc->n_elem - 1].flags_size |= EPRD_FLAG_END_OF_TBL; + if (ata_sg_is_last(sg, qc)) + pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); + + i++; } } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 19857814d69f..e16d1815cda0 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -416,15 +416,20 @@ static void sil24_phy_reset(struct ata_port *ap) static inline void sil24_fill_sg(struct ata_queued_cmd *qc, struct sil24_cmd_block *cb) { - struct scatterlist *sg = qc->sg; struct sil24_sge *sge = cb->sge; - unsigned i; + struct scatterlist *sg; + unsigned int idx = 0; - for (i = 0; i < qc->n_elem; i++, sg++, sge++) { + ata_for_each_sg(sg, qc) { sge->addr = cpu_to_le64(sg_dma_address(sg)); sge->cnt = cpu_to_le32(sg_dma_len(sg)); - sge->flags = 0; - sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM); + if (ata_sg_is_last(sg, qc)) + sge->flags = cpu_to_le32(SGE_TRM); + else + sge->flags = 0; + + sge++; + idx++; } } diff --git a/include/linux/libata.h b/include/linux/libata.h index d3f58a796c3a..d3dfefefabec 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -480,6 +480,18 @@ extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); #endif /* CONFIG_PCI */ +static inline int +ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) +{ + if (sg == &qc->pad_sgent) + return 1; + if (qc->pad_len) + return 0; + if (((sg - qc->__sg) + 1) == qc->n_elem) + return 1; + return 0; +} + static inline struct scatterlist * ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) { -- cgit v1.2.3 From 9ccfc756a70d454dfa82f48897e2883560c01a0e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 2 Oct 2005 11:45:08 -0500 Subject: [SCSI] move the mid-layer printk's over to shost/starget/sdev_printk This should eliminate (at least in the mid layer) to make numeric assumptions about any of the enumeration variables. As a side effect, it will also make all the messages consistent and line us up nicely for the error logging strategy (if it ever shows itself again). Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 5 +---- drivers/scsi/hosts.c | 10 ++++----- drivers/scsi/osst.c | 6 ++--- drivers/scsi/scsi.c | 21 +++++++----------- drivers/scsi/scsi_error.c | 25 ++++++++------------- drivers/scsi/scsi_ioctl.c | 10 +++------ drivers/scsi/scsi_lib.c | 46 +++++++++++++++++++-------------------- drivers/scsi/scsi_scan.c | 7 +++--- drivers/scsi/scsi_transport_fc.c | 2 -- drivers/scsi/scsi_transport_spi.c | 24 ++++++++++---------- drivers/scsi/sd.c | 10 ++++----- drivers/scsi/sg.c | 14 +++++------- drivers/scsi/sr.c | 15 ++++++------- drivers/scsi/st.c | 10 ++++----- include/scsi/scsi_device.h | 6 +++++ include/scsi/scsi_host.h | 4 ++++ 16 files changed, 96 insertions(+), 119 deletions(-) (limited to 'include') diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index f6be2c1c3942..09bc81557b6e 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1389,10 +1389,7 @@ EXPORT_SYMBOL(scsi_print_msg); void scsi_print_command(struct scsi_cmnd *cmd) { /* Assume appended output (i.e. not at start of line) */ - printk("scsi%d : destination target %d, lun %d\n", - cmd->device->host->host_no, - cmd->device->id, - cmd->device->lun); + sdev_printk("", cmd->device, "\n"); printk(KERN_INFO " command: "); scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0); } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f24d84538fd5..0d48c9ceebd3 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -139,11 +139,11 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) illegal: SCSI_LOG_ERROR_RECOVERY(1, - dev_printk(KERN_ERR, &shost->shost_gendev, - "Illegal host state transition" - "%s->%s\n", - scsi_host_state_name(oldstate), - scsi_host_state_name(state))); + shost_printk(KERN_ERR, shost, + "Illegal host state transition" + "%s->%s\n", + scsi_host_state_name(oldstate), + scsi_host_state_name(state))); return -EINVAL; } EXPORT_SYMBOL(scsi_host_set_state); diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index af1133104b3f..c1131c9cae64 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5819,9 +5819,9 @@ static int osst_probe(struct device *dev) } drive->number = devfs_register_tape(SDp->devfs_name); - printk(KERN_INFO - "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n", - SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt)); + dev_printk(KERN_INFO, &SDp->sdev_gendev, + "osst :I: Attached OnStream %.5s tape as %s\n", + SDp->model, tape_name(tpnt)); return 0; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a5711d545d71..071d109b4b2a 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -410,9 +410,7 @@ void scsi_log_send(struct scsi_cmnd *cmd) SCSI_LOG_MLQUEUE_BITS); if (level > 1) { sdev = cmd->device; - printk(KERN_INFO "scsi <%d:%d:%d:%d> send ", - sdev->host->host_no, sdev->channel, sdev->id, - sdev->lun); + sdev_printk(KERN_INFO, sdev, "send "); if (level > 2) printk("0x%p ", cmd); /* @@ -456,9 +454,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) if (((level > 0) && (cmd->result || disposition != SUCCESS)) || (level > 1)) { sdev = cmd->device; - printk(KERN_INFO "scsi <%d:%d:%d:%d> done ", - sdev->host->host_no, sdev->channel, sdev->id, - sdev->lun); + sdev_printk(KERN_INFO, sdev, "done "); if (level > 2) printk("0x%p ", cmd); /* @@ -810,9 +806,9 @@ static void scsi_softirq(struct softirq_action *h) disposition = scsi_decide_disposition(cmd); if (disposition != SUCCESS && time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { - dev_printk(KERN_ERR, &cmd->device->sdev_gendev, - "timing out command, waited %lus\n", - wait_for/HZ); + sdev_printk(KERN_ERR, cmd->device, + "timing out command, waited %lus\n", + wait_for/HZ); disposition = SUCCESS; } @@ -970,10 +966,9 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) sdev->simple_tags = 1; break; default: - printk(KERN_WARNING "(scsi%d:%d:%d:%d) " - "scsi_adjust_queue_depth, bad queue type, " - "disabled\n", sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun); + sdev_printk(KERN_WARNING, sdev, + "scsi_adjust_queue_depth, bad queue type, " + "disabled\n"); case 0: sdev->ordered_tags = sdev->simple_tags = 0; sdev->queue_depth = tags; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 52b348c36d56..dd6a9f61bdf1 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -241,11 +241,10 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, if (cmd_cancel || cmd_failed) { SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: %d:%d:%d:%d cmds failed: %d," - " cancel: %d\n", - __FUNCTION__, shost->host_no, - sdev->channel, sdev->id, sdev->lun, - cmd_failed, cmd_cancel)); + sdev_printk(KERN_INFO, sdev, + "%s: cmds failed: %d, cancel: %d\n", + __FUNCTION__, cmd_failed, + cmd_cancel)); cmd_cancel = 0; cmd_failed = 0; ++devices_failed; @@ -1174,13 +1173,9 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q, struct scsi_cmnd *scmd, *next; list_for_each_entry_safe(scmd, next, work_q, eh_entry) { - printk(KERN_INFO "scsi: Device offlined - not" - " ready after error recovery: host" - " %d channel %d id %d lun %d\n", - scmd->device->host->host_no, - scmd->device->channel, - scmd->device->id, - scmd->device->lun); + sdev_printk(KERN_INFO, scmd->device, + "scsi: Device offlined - not" + " ready after error recovery\n"); scsi_device_set_state(scmd->device, SDEV_OFFLINE); if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) { /* @@ -1342,10 +1337,8 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) return SUCCESS; case RESERVATION_CONFLICT: - printk(KERN_INFO "scsi: reservation conflict: host" - " %d channel %d id %d lun %d\n", - scmd->device->host->host_no, scmd->device->channel, - scmd->device->id, scmd->device->lun); + sdev_printk(KERN_INFO, scmd->device, + "reservation conflict\n"); return SUCCESS; /* causes immediate i/o error */ default: return FAILED; diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 6a3f6aae8a97..26f5bc6d9c82 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -122,13 +122,9 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, break; } default: /* Fall through for non-removable media */ - printk(KERN_INFO "ioctl_internal_command: <%d %d %d " - "%d> return code = %x\n", - sdev->host->host_no, - sdev->channel, - sdev->id, - sdev->lun, - result); + sdev_printk(KERN_INFO, sdev, + "ioctl_internal_command return code = %x\n", + result); scsi_print_sense_hdr(" ", &sshdr); break; } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3ff538809786..19ac888001e6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -951,16 +951,16 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, return; } if (!(req->flags & REQ_QUIET)) - dev_printk(KERN_INFO, - &cmd->device->sdev_gendev, - "Device not ready.\n"); + sdev_printk(KERN_INFO, + cmd->device, + "Device not ready.\n"); scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: if (!(req->flags & REQ_QUIET)) { - dev_printk(KERN_INFO, - &cmd->device->sdev_gendev, - "Volume overflow, CDB: "); + sdev_printk(KERN_INFO, + cmd->device, + "Volume overflow, CDB: "); __scsi_print_command(cmd->data_cmnd); scsi_print_sense("", cmd); } @@ -981,8 +981,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, } if (result) { if (!(req->flags & REQ_QUIET)) { - dev_printk(KERN_INFO, &cmd->device->sdev_gendev, - "SCSI error: return code = 0x%x\n", result); + sdev_printk(KERN_INFO, cmd->device, + "SCSI error: return code = 0x%x\n", + result); if (driver_byte(result) & DRIVER_SENSE) scsi_print_sense("", cmd); @@ -1141,8 +1142,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) * online before trying any recovery commands */ if (unlikely(!scsi_device_online(sdev))) { - printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", - sdev->host->host_no, sdev->id, sdev->lun); + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to offline device\n"); goto kill; } if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { @@ -1151,8 +1152,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) if (sdev->sdev_state == SDEV_DEL) { /* Device is fully deleted, no commands * at all allowed down */ - printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n", - sdev->host->host_no, sdev->id, sdev->lun); + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to dead device\n"); goto kill; } /* OK, we only allow special commands (i.e. not @@ -1187,8 +1188,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) specials_only == SDEV_BLOCK) goto defer; - printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n", - sdev->host->host_no, sdev->id, sdev->lun); + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to device being removed\n"); goto kill; } @@ -1315,9 +1316,8 @@ static inline int scsi_dev_queue_ready(struct request_queue *q, */ if (--sdev->device_blocked == 0) { SCSI_LOG_MLQUEUE(3, - printk("scsi%d (%d:%d) unblocking device at" - " zero depth\n", sdev->host->host_no, - sdev->id, sdev->lun)); + sdev_printk(KERN_INFO, sdev, + "unblocking device at zero depth\n")); } else { blk_plug_device(q); return 0; @@ -1436,8 +1436,8 @@ static void scsi_request_fn(struct request_queue *q) break; if (unlikely(!scsi_device_online(sdev))) { - printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", - sdev->host->host_no, sdev->id, sdev->lun); + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to offline device\n"); scsi_kill_request(req, q); continue; } @@ -1893,10 +1893,10 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) illegal: SCSI_LOG_ERROR_RECOVERY(1, - dev_printk(KERN_ERR, &sdev->sdev_gendev, - "Illegal state transition %s->%s\n", - scsi_device_state_name(oldstate), - scsi_device_state_name(state)) + sdev_printk(KERN_ERR, sdev, + "Illegal state transition %s->%s\n", + scsi_device_state_name(oldstate), + scsi_device_state_name(state)) ); return -EINVAL; } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 327c5d7e5bd2..ce8456c3b718 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -462,10 +462,9 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, pass = 1; next_pass: - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY pass %d " - "to host %d channel %d id %d lun %d, length %d\n", - pass, sdev->host->host_no, sdev->channel, - sdev->id, sdev->lun, try_inquiry_len)); + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, + "scsi scan: INQUIRY pass %d length %d\n", + pass, try_inquiry_len)); /* Each pass gets up to three chances to ignore Unit Attention */ for (count = 0; count < 3; ++count) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 771e97ef136e..473a82d5e3e2 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -32,8 +32,6 @@ #include #include "scsi_priv.h" -#define FC_PRINTK(x, l, f, a...) printk(l "scsi(%d:%d:%d:%d): " f, (x)->host->host_no, (x)->channel, (x)->id, (x)->lun , ##a) - /* * Redefine so that we can have same named attributes in the * sdev/starget/host objects. diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index ef577c8c2182..718a2bc4ed5e 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -33,8 +33,6 @@ #include #include -#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) - #define SPI_NUM_ATTRS 14 /* increase this if you add attributes */ #define SPI_OTHER_ATTRS 1 /* Increase this if you add "always * on" attributes */ @@ -618,7 +616,7 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer, return SPI_COMPARE_SKIP_TEST; - SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result); + sdev_printk(KERN_ERR, sdev, "Write Buffer failure %x\n", result); return SPI_COMPARE_FAILURE; } @@ -702,10 +700,10 @@ spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr, * IU, then QAS (if we can control them), then finally * fall down the periods */ if (i->f->set_iu && spi_iu(starget)) { - SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Information Units\n"); + starget_printk(KERN_ERR, starget, "Domain Validation Disabing Information Units\n"); DV_SET(iu, 0); } else if (i->f->set_qas && spi_qas(starget)) { - SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Quick Arbitration and Selection\n"); + starget_printk(KERN_ERR, starget, "Domain Validation Disabing Quick Arbitration and Selection\n"); DV_SET(qas, 0); } else { newperiod = spi_period(starget); @@ -717,11 +715,11 @@ spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr, if (unlikely(period > 0xff || period == prevperiod)) { /* Total failure; set to async and return */ - SPI_PRINTK(starget, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); + starget_printk(KERN_ERR, starget, "Domain Validation Failure, dropping back to Asynchronous\n"); DV_SET(offset, 0); return SPI_COMPARE_FAILURE; } - SPI_PRINTK(starget, KERN_ERR, "Domain Validation detected failure, dropping back\n"); + starget_printk(KERN_ERR, starget, "Domain Validation detected failure, dropping back\n"); DV_SET(period, period); prevperiod = period; } @@ -788,7 +786,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) != SPI_COMPARE_SUCCESS) { - SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); + starget_printk(KERN_ERR, starget, "Domain Validation Initial Inquiry Failed\n"); /* FIXME: should probably offline the device here? */ return; } @@ -802,7 +800,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) buffer + len, DV_LOOPS) != SPI_COMPARE_SUCCESS) { - SPI_PRINTK(starget, KERN_ERR, "Wide Transfers Fail\n"); + starget_printk(KERN_ERR, starget, "Wide Transfers Fail\n"); i->f->set_width(starget, 0); } } @@ -844,14 +842,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) } if (len == 0) { - SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); + starget_printk(KERN_INFO, starget, "Domain Validation skipping write tests\n"); spi_dv_retrain(sdev, buffer, buffer + len, spi_dv_device_compare_inquiry); return; } if (len > SPI_MAX_ECHO_BUFFER_SIZE) { - SPI_PRINTK(starget, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); + starget_printk(KERN_WARNING, starget, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); len = SPI_MAX_ECHO_BUFFER_SIZE; } @@ -902,11 +900,11 @@ spi_dv_device(struct scsi_device *sdev) spi_dv_pending(starget) = 1; down(&spi_dv_sem(starget)); - SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); + starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n"); spi_dv_device_internal(sdev, buffer); - SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); + starget_printk(KERN_INFO, starget, "Ending Domain Validation\n"); up(&spi_dv_sem(starget)); spi_dv_pending(starget) = 0; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 98da5c8057bf..9de8e186cb69 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1534,8 +1534,8 @@ static int sd_probe(struct device *dev) if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC) goto out; - SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", - sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); + SCSI_LOG_HLQUEUE(3, sdev_printk(KERN_INFO, sdp, + "sd_attach\n")); error = -ENOMEM; sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL); @@ -1607,10 +1607,8 @@ static int sd_probe(struct device *dev) dev_set_drvdata(dev, sdkp); add_disk(gd); - printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, " - "id %d, lun %d\n", sdp->removable ? "removable " : "", - gd->disk_name, sdp->host->host_no, sdp->channel, - sdp->id, sdp->lun); + sdev_printk(KERN_NOTICE, sdp, "Attached scsi %sdisk %s\n", + sdp->removable ? "removable " : "", gd->disk_name); return 0; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index fd56b7ec88b6..49b9269d487a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1497,10 +1497,9 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) overflow: write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_WARNING - "Unable to attach sg device <%d, %d, %d, %d> type=%d, minor " - "number exceeds %d\n", scsidp->host->host_no, scsidp->channel, - scsidp->id, scsidp->lun, scsidp->type, SG_MAX_DEVS - 1); + sdev_printk(KERN_WARNING, scsidp, + "Unable to attach sg device type=%d, minor " + "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1); error = -ENODEV; goto out; } @@ -1566,11 +1565,8 @@ sg_add(struct class_device *cl_dev) } else printk(KERN_WARNING "sg_add: sg_sys INvalid\n"); - printk(KERN_NOTICE - "Attached scsi generic sg%d at scsi%d, channel" - " %d, id %d, lun %d, type %d\n", k, - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, scsidp->type); + sdev_printk(KERN_NOTICE, scsidp, + "Attached scsi generic sg%d type %d\n", k,scsidp->type); return 0; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 561901b1cf11..9e267c6d3a43 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -360,7 +360,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) } if (s_size != 512 && s_size != 1024 && s_size != 2048) { - printk("sr: bad sector size %d\n", s_size); + sdev_printk(KERN_ERR, SCpnt->device, "bad sector size %d\n", s_size); return 0; } @@ -385,8 +385,9 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) size += sg[i].length; if (size != SCpnt->request_bufflen && SCpnt->use_sg) { - printk(KERN_ERR "sr: mismatch count %d, bytes %d\n", - size, SCpnt->request_bufflen); + sdev_printk(KERN_ERR, SCpnt->device, + "mismatch count %d, bytes %d\n", + size, SCpnt->request_bufflen); if (SCpnt->request_bufflen > size) SCpnt->request_bufflen = SCpnt->bufflen = size; } @@ -397,7 +398,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) */ if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) || (SCpnt->request_bufflen % s_size)) { - printk("sr: unaligned transfer\n"); + sdev_printk(KERN_NOTICE, SCpnt->device, "unaligned transfer\n"); return 0; } @@ -622,10 +623,8 @@ static int sr_probe(struct device *dev) disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); - printk(KERN_DEBUG - "Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n", - cd->cdi.name, sdev->host->host_no, sdev->channel, - sdev->id, sdev->lun); + sdev_printk(KERN_DEBUG, sdev, + "Attached scsi CD-ROM %s\n", cd->cdi.name); return 0; fail_put: diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 927d700f0073..dc5ffc16a252 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3887,9 +3887,8 @@ static int st_probe(struct device *dev) if (SDp->type != TYPE_TAPE) return -ENODEV; if ((stp = st_incompatible(SDp))) { - printk(KERN_INFO - "st: Found incompatible tape at scsi%d, channel %d, id %d, lun %d\n", - SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); + sdev_printk(KERN_INFO, SDp, + "Found incompatible tape\n"); printk(KERN_INFO "st: The suggested driver is %s.\n", stp); return -ENODEV; } @@ -4077,9 +4076,8 @@ static int st_probe(struct device *dev) } disk->number = devfs_register_tape(SDp->devfs_name); - printk(KERN_WARNING - "Attached scsi tape %s at scsi%d, channel %d, id %d, lun %d\n", - tape_name(tpnt), SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); + sdev_printk(KERN_WARNING, SDp, + "Attached scsi tape %s", tape_name(tpnt)); printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B), max page reachable by HBA %lu\n", tape_name(tpnt), tpnt->try_dio ? "yes" : "no", queue_dma_alignment(SDp->request_queue) + 1, tpnt->max_pfn); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 7ece05666feb..7f621ab2865d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -148,6 +148,9 @@ struct scsi_device { #define transport_class_to_sdev(class_dev) \ to_scsi_device(class_dev->dev) +#define sdev_printk(prefix, sdev, fmt, a...) \ + dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a) + /* * scsi_target: representation of a scsi target, for now, this is only * used for single_lun devices. If no one has active IO to the target, @@ -177,6 +180,9 @@ static inline struct scsi_target *scsi_target(struct scsi_device *sdev) #define transport_class_to_starget(class_dev) \ to_scsi_target(class_dev->dev) +#define starget_printk(prefix, starget, fmt, a...) \ + dev_printk(prefix, &(starget)->dev, fmt, ##a) + extern struct scsi_device *__scsi_add_device(struct Scsi_Host *, uint, uint, uint, void *hostdata); extern int scsi_add_device(struct Scsi_Host *host, uint channel, diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 69313ba7505b..ea7ad7235397 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -609,6 +609,10 @@ struct Scsi_Host { #define class_to_shost(d) \ container_of(d, struct Scsi_Host, shost_classdev) +#define shost_printk(prefix, shost, fmt, a...) \ + dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a) + + int scsi_is_host_device(const struct device *); static inline struct Scsi_Host *dev_to_shost(struct device *dev) -- cgit v1.2.3 From c3ee74c4e91017169c7f1fa74a57ba8502ec49c3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Sep 2005 21:59:42 +0200 Subject: [SCSI] scsi_transport_sas: support link error attributes For now supporting the ->get_linkerrors method is mandatory. I'll probably be beaten to implement the .show_foo variables and different types of attributes soon.. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 31 ++++++++++++++++++++++++++++++- include/scsi/scsi_transport_sas.h | 23 +++++++++++++++++++---- 2 files changed, 49 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 1d145d2f9a38..63445f90097e 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -34,7 +34,7 @@ #define SAS_HOST_ATTRS 0 -#define SAS_PORT_ATTRS 11 +#define SAS_PORT_ATTRS 15 #define SAS_RPORT_ATTRS 5 struct sas_internal { @@ -257,6 +257,26 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \ sas_phy_show_linkspeed(field) \ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) +#define sas_phy_show_linkerror(field) \ +static ssize_t \ +show_sas_phy_##field(struct class_device *cdev, char *buf) \ +{ \ + struct sas_phy *phy = transport_class_to_phy(cdev); \ + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ + struct sas_internal *i = to_sas_internal(shost->transportt); \ + int error; \ + \ + error = i->f->get_linkerrors(phy); \ + if (error) \ + return error; \ + return snprintf(buf, 20, "%u\n", phy->field); \ +} + +#define sas_phy_linkerror_attr(field) \ + sas_phy_show_linkerror(field) \ +static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) + + static ssize_t show_sas_device_type(struct class_device *cdev, char *buf) { @@ -282,6 +302,10 @@ sas_phy_linkspeed_attr(minimum_linkrate_hw); sas_phy_linkspeed_attr(minimum_linkrate); sas_phy_linkspeed_attr(maximum_linkrate_hw); sas_phy_linkspeed_attr(maximum_linkrate); +sas_phy_linkerror_attr(invalid_dword_count); +sas_phy_linkerror_attr(running_disparity_error_count); +sas_phy_linkerror_attr(loss_of_dword_sync_count); +sas_phy_linkerror_attr(phy_reset_problem_count); static DECLARE_TRANSPORT_CLASS(sas_phy_class, @@ -749,6 +773,11 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_PORT_ATTRIBUTE(minimum_linkrate); SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); SETUP_PORT_ATTRIBUTE(maximum_linkrate); + + SETUP_PORT_ATTRIBUTE(invalid_dword_count); + SETUP_PORT_ATTRIBUTE(running_disparity_error_count); + SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); + SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); i->phy_attrs[count] = NULL; count = 0; diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index bc4aeb660dd3..38389d8dd56e 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -41,20 +41,28 @@ struct sas_identify { u8 phy_identifier; }; -/* The functions by which the transport class and the driver communicate */ -struct sas_function_template { -}; - struct sas_phy { struct device dev; int number; + + /* phy identification */ struct sas_identify identify; + + /* phy attributes */ enum sas_linkrate negotiated_linkrate; enum sas_linkrate minimum_linkrate_hw; enum sas_linkrate minimum_linkrate; enum sas_linkrate maximum_linkrate_hw; enum sas_linkrate maximum_linkrate; u8 port_identifier; + + /* link error statistics */ + u32 invalid_dword_count; + u32 running_disparity_error_count; + u32 loss_of_dword_sync_count; + u32 phy_reset_problem_count; + + /* the other end of the link */ struct sas_rphy *rphy; }; @@ -79,6 +87,13 @@ struct sas_rphy { #define rphy_to_shost(rphy) \ dev_to_shost((rphy)->dev.parent) + +/* The functions by which the transport class and the driver communicate */ +struct sas_function_template { + int (*get_linkerrors)(struct sas_phy *); +}; + + extern void sas_remove_host(struct Scsi_Host *); extern struct sas_phy *sas_phy_alloc(struct device *, int); -- cgit v1.2.3 From ac01bbbd3b7ebfca64357aed12cf476b16abe3ce Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 19 Oct 2005 20:01:17 +0200 Subject: [SCSI] sas: add flag for locally attached PHYs Add a flag to mark a PHY as attached to the HBA as opposed to beeing on an expander. This is needed because various features are only supported on those. This is a crude hack, the proper fix would be to use different classes for host-attached vs expander phys. I'm looking into that. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 10 +++++++--- drivers/scsi/scsi_transport_sas.c | 3 +++ include/scsi/scsi_transport_sas.h | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 6512027bc69a..dcdf0380be86 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -760,7 +760,7 @@ mptsas_parse_device_info(struct sas_identify *identify, } static int mptsas_probe_one_phy(struct device *dev, - struct mptsas_phyinfo *phy_info, int index) + struct mptsas_phyinfo *phy_info, int index, int local) { struct sas_phy *port; int error; @@ -853,6 +853,9 @@ static int mptsas_probe_one_phy(struct device *dev, break; } + if (local) + port->local_attached = 1; + error = sas_phy_add(port); if (error) { sas_phy_free(port); @@ -918,7 +921,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) } mptsas_probe_one_phy(&ioc->sh->shost_gendev, - &port_info->phy_info[i], *index); + &port_info->phy_info[i], *index, 1); (*index)++; } @@ -989,7 +992,8 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) } } - mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index); + mptsas_probe_one_phy(parent, &port_info->phy_info[i], + *index, 0); (*index)++; } diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 63445f90097e..f5618c1116f4 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -266,6 +266,9 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \ struct sas_internal *i = to_sas_internal(shost->transportt); \ int error; \ \ + if (!phy->local_attached) \ + return -EINVAL; \ + \ error = i->f->get_linkerrors(phy); \ if (error) \ return error; \ diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 38389d8dd56e..57eb68c6e9a7 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -56,6 +56,9 @@ struct sas_phy { enum sas_linkrate maximum_linkrate; u8 port_identifier; + /* internal state */ + unsigned int local_attached : 1; + /* link error statistics */ u32 invalid_dword_count; u32 running_disparity_error_count; -- cgit v1.2.3 From 07ba3a954714da10cbd3f6249d93ac2c1df72c4f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 19 Oct 2005 20:01:31 +0200 Subject: [SCSI] sas: add support for PHY resets Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 43 +++++++++++++++++++++++++++++++++++++-- include/scsi/scsi_transport_sas.h | 1 + 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index f5618c1116f4..0cc766a9aa65 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -34,7 +34,7 @@ #define SAS_HOST_ATTRS 0 -#define SAS_PORT_ATTRS 15 +#define SAS_PORT_ATTRS 17 #define SAS_RPORT_ATTRS 5 struct sas_internal { @@ -289,9 +289,39 @@ show_sas_device_type(struct class_device *cdev, char *buf) return snprintf(buf, 20, "none\n"); return get_sas_device_type_names(phy->identify.device_type, buf); } - static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); +static ssize_t do_sas_phy_reset(struct class_device *cdev, + size_t count, int hard_reset) +{ + struct sas_phy *phy = transport_class_to_phy(cdev); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + int error; + + if (!phy->local_attached) + return -EINVAL; + + error = i->f->phy_reset(phy, hard_reset); + if (error) + return error; + return count; +}; + +static ssize_t store_sas_link_reset(struct class_device *cdev, + const char *buf, size_t count) +{ + return do_sas_phy_reset(cdev, count, 0); +} +static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); + +static ssize_t store_sas_hard_reset(struct class_device *cdev, + const char *buf, size_t count) +{ + return do_sas_phy_reset(cdev, count, 1); +} +static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); + sas_phy_protocol_attr(identify.initiator_port_protocols, initiator_port_protocols); sas_phy_protocol_attr(identify.target_port_protocols, @@ -725,6 +755,13 @@ static struct device *sas_target_parent(struct Scsi_Host *shost, i->phy_attrs[count] = &i->private_phy_attrs[count]; \ count++ +#define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ + i->private_phy_attrs[count] = class_device_attr_##field; \ + i->private_phy_attrs[count].attr.mode = S_IWUGO; \ + i->private_phy_attrs[count].show = NULL; \ + i->phy_attrs[count] = &i->private_phy_attrs[count]; \ + count++ + /** * sas_attach_transport -- instantiate SAS transport template @@ -781,6 +818,8 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_PORT_ATTRIBUTE(running_disparity_error_count); SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); + SETUP_PORT_ATTRIBUTE_WRONLY(link_reset); + SETUP_PORT_ATTRIBUTE_WRONLY(hard_reset); i->phy_attrs[count] = NULL; count = 0; diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 57eb68c6e9a7..b91400bfb02a 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -94,6 +94,7 @@ struct sas_rphy { /* The functions by which the transport class and the driver communicate */ struct sas_function_template { int (*get_linkerrors)(struct sas_phy *); + int (*phy_reset)(struct sas_phy *, int); }; -- cgit v1.2.3 From 91ca7b01ecc916632202180569a7ddbfccfc3f05 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 27 Oct 2005 16:03:37 -0700 Subject: [SCSI] Add an 'Issue LIP' device attribute in fc_transport class Ok, here's a patch to add such a common API for fc transport users. Relevant LLD changes (lpfc and qla2xxx) also present. Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 16 +++++----------- drivers/scsi/qla2xxx/qla_attr.c | 10 ++++++++++ drivers/scsi/qla2xxx/qla_os.c | 7 +++++++ drivers/scsi/scsi_transport_fc.c | 28 ++++++++++++++++++++++++++-- include/scsi/scsi_transport_fc.h | 2 ++ 5 files changed, 50 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index acae7c48ef7d..445da1d0cc88 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -200,19 +200,13 @@ lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf) } -static ssize_t -lpfc_issue_lip (struct class_device *cdev, const char *buf, size_t count) +static int +lpfc_issue_lip(struct Scsi_Host *host) { - struct Scsi_Host *host = class_to_shost(cdev); struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0]; - int val = 0; LPFC_MBOXQ_t *pmboxq; int mbxstatus = MBXERR_ERROR; - if ((sscanf(buf, "%d", &val) != 1) || - (val != 1)) - return -EINVAL; - if ((phba->fc_flag & FC_OFFLINE_MODE) || (phba->hba_state != LPFC_HBA_READY)) return -EPERM; @@ -234,7 +228,7 @@ lpfc_issue_lip (struct class_device *cdev, const char *buf, size_t count) if (mbxstatus == MBXERR_ERROR) return -EIO; - return strlen(buf); + return 0; } static ssize_t @@ -364,7 +358,6 @@ static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show, NULL); static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show, NULL); -static CLASS_DEVICE_ATTR(issue_lip, S_IWUSR, NULL, lpfc_issue_lip); static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR, lpfc_board_online_show, lpfc_board_online_store); @@ -537,7 +530,6 @@ struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_lpfc_max_luns, &class_device_attr_nport_evt_cnt, &class_device_attr_management_version, - &class_device_attr_issue_lip, &class_device_attr_board_online, NULL, }; @@ -1234,6 +1226,8 @@ struct fc_function_template lpfc_transport_functions = { .get_starget_port_name = lpfc_get_starget_port_name, .show_starget_port_name = 1, + + .issue_fc_host_lip = lpfc_issue_lip, }; void diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 49696faa24fa..48e460eef05a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -503,6 +503,15 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) rport->dev_loss_tmo = ha->port_down_retry_count + 5; } +static int +qla2x00_issue_lip(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + + set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); + return 0; +} + struct fc_function_template qla2xxx_transport_functions = { .show_host_node_name = 1, @@ -526,6 +535,7 @@ struct fc_function_template qla2xxx_transport_functions = { .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, .show_rport_dev_loss_tmo = 1, + .issue_fc_host_lip = qla2x00_issue_lip, }; void diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d9eccdf4f403..b899282a856e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2141,6 +2141,12 @@ qla2x00_do_dpc(void *data) ha->host_no)); } + if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) { + DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n", + ha->host_no)); + qla2x00_loop_reset(ha); + } + if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) && (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) { @@ -2442,6 +2448,7 @@ qla2x00_timer(scsi_qla_host_t *ha) /* Schedule the DPC routine if needed */ if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || + test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) || start_dpc || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 473a82d5e3e2..27702097b7fc 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -220,7 +220,7 @@ static void fc_rport_terminate(struct fc_rport *rport); */ #define FC_STARGET_NUM_ATTRS 3 #define FC_RPORT_NUM_ATTRS 9 -#define FC_HOST_NUM_ATTRS 15 +#define FC_HOST_NUM_ATTRS 16 struct fc_internal { struct scsi_transport_template t; @@ -713,9 +713,11 @@ static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ count++ #define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field) \ +{ \ i->private_host_attrs[count] = class_device_attr_host_##field; \ i->host_attrs[count] = &i->private_host_attrs[count]; \ - count++ + count++; \ +} /* Fixed Host Attributes */ @@ -853,6 +855,26 @@ static FC_CLASS_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR, show_fc_private_host_tgtid_bind_type, store_fc_private_host_tgtid_bind_type); +static ssize_t +store_fc_private_host_issue_lip(struct class_device *cdev, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct fc_internal *i = to_fc_internal(shost->transportt); + int ret; + + /* ignore any data value written to the attribute */ + if (i->f->issue_fc_host_lip) { + ret = i->f->issue_fc_host_lip(shost); + return ret ? ret: count; + } + + return -ENOENT; +} + +static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL, + store_fc_private_host_issue_lip); + /* * Host Statistics Management */ @@ -1119,6 +1141,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport-managed attributes */ SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); + if (ft->issue_fc_host_lip) + SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip); BUG_ON(count > FC_HOST_NUM_ATTRS); diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index b0d445437372..4496b32972e5 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -384,6 +384,8 @@ struct fc_function_template { struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *); void (*reset_fc_host_stats)(struct Scsi_Host *); + int (*issue_fc_host_lip)(struct Scsi_Host *); + /* allocation lengths for host-specific data */ u32 dd_fcrport_size; -- cgit v1.2.3 From 13ec92b33e4f41b81b3a237ad1d9a588a81f2f03 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 24 Oct 2005 18:01:11 -0400 Subject: [SCSI] kill unused scsi_scan_single_target() Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 13 ------------- include/scsi/scsi_host.h | 2 -- 2 files changed, 15 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index ce8456c3b718..e8f6fee34c94 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1451,19 +1451,6 @@ void scsi_scan_host(struct Scsi_Host *shost) } EXPORT_SYMBOL(scsi_scan_host); -/** - * scsi_scan_single_target - scan the given SCSI target - * @shost: adapter to scan - * @chan: channel to scan - * @id: target id to scan - **/ -void scsi_scan_single_target(struct Scsi_Host *shost, - unsigned int chan, unsigned int id) -{ - scsi_scan_host_selected(shost, chan, id, SCAN_WILD_CARD, 1); -} -EXPORT_SYMBOL(scsi_scan_single_target); - void scsi_forget_host(struct Scsi_Host *shost) { struct scsi_device *sdev; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index ea7ad7235397..ecd53d7872d2 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -638,8 +638,6 @@ extern void scsi_flush_work(struct Scsi_Host *); extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int); extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *); extern void scsi_scan_host(struct Scsi_Host *); -extern void scsi_scan_single_target(struct Scsi_Host *, unsigned int, - unsigned int); extern void scsi_rescan_device(struct device *); extern void scsi_remove_host(struct Scsi_Host *); extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *); -- cgit v1.2.3 From 01d7b3b8d09ef78e2c835c03d97ea1d91c26e245 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 24 Oct 2005 18:03:34 -0400 Subject: [SCSI] introduce sfoo_printk, sfoo_id, sfoo_channel helpers New dev_printk wrappers, which allow us to shrink code, and eliminate direct references to host/channel/id/lun members: scmd_printk() Introduce wrappers for highly common idioms, which may also help us eliminate some ->{channel,id} references in the future: {scmd,sdev}_id() {scmd,sdev}_channel() The scmd_* wrappers are present in scsi/scsi_device.h because they all employ the dereference chain cmd->device->$member. We would prefer to use static inline functions rather than macros, but that would have a Rejections fixed up and Signed-off-by: James Bottomley --- include/scsi/scsi_device.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include') diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 7f621ab2865d..85cfd88461c8 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -151,6 +151,9 @@ struct scsi_device { #define sdev_printk(prefix, sdev, fmt, a...) \ dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a) +#define scmd_printk(prefix, scmd, fmt, a...) \ + dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a) + /* * scsi_target: representation of a scsi target, for now, this is only * used for single_lun devices. If no one has active IO to the target, @@ -272,6 +275,19 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *, int timeout, int retries); +static inline unsigned int sdev_channel(struct scsi_device *sdev) +{ + return sdev->channel; +} + +static inline unsigned int sdev_id(struct scsi_device *sdev) +{ + return sdev->id; +} + +#define scmd_id(scmd) sdev_id((scmd)->device) +#define scmd_channel(scmd) sdev_channel((scmd)->device) + static inline int scsi_device_online(struct scsi_device *sdev) { return sdev->sdev_state != SDEV_OFFLINE; -- cgit v1.2.3 From 19a7b4aebf9ad435c69a7e39930338499af4d152 Mon Sep 17 00:00:00 2001 From: "James.Smart@Emulex.Com" Date: Tue, 18 Oct 2005 12:03:35 -0400 Subject: [SCSI] update fc_transport for removal of block/unblock functions We recently went back to implement a board reset. When we perform the reset, we wanted to tear down the internal data structures and rebuild them. Unfortunately, when it came to the rport structure, things were odd. If we deleted them, the scsi targets and sdevs would be torn down. Not a good thing for a temporary reset. We could block the rports, but we either maintain the internal structures to keep the rport reference (perhaps even replicating what's in the transport), or we have to fatten the fc transport with new search routines to find the rport (and deal with a case of a dangling rport that the driver forgets). It dawned on me that we had actually reached this state incorrectly. When the fc transport first started, we did the block/unblock first, then added the rport interface. The purpose of block/unblock is to hide the temporary disappearance of the rport (e.g. being deleted, then readded). Why are we making the driver do the block/unblock ? We should be making the transport have only an rport add/delete, and the let the transport handle the block/unblock. So... This patch removes the existing fc_remote_port_block/unblock functions. It moves the block/unblock functionality into the fc_remote_port_add/delete functions. Updates for the lpfc driver are included. Qlogic driver updates are also enclosed, thanks to the contributions of Andrew Vasquez. [Note: the qla2xxx changes are relative to the scsi-misc-2.6 tree as of this morning - which does not include the recent patches sent by Andrew]. The zfcp driver does not use the block/unblock functions. One last comment: The resulting behavior feels very clean. The LLDD is concerned only with add/delete, which corresponds to the physical disappearance. However, the fact that the scsi target and sdevs are not immediately torn down after the LLDD calls delete causes an interesting scenario... the midlayer can call the xxx_slave_alloc and xxx_queuecommand functions with a sdev that is at the location the rport used to be. The driver must validate the device exists when it first enters these functions. In thinking about it, this has always been the case for the LLDD and these routines. The existing drivers already check for existence. However, this highlights that simple validation via data structure dereferencing needs to be watched. To deal with this, a new transport function, fc_remote_port_chkready() was created that LLDDs should call when they first enter these two routines. It validates the rport state, and returns a scsi result which could be returned. In addition to solving the above, it also creates consistent behavior from the LLDD's when the block and deletes are occuring. Rejections fixed up and Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 28 ++- drivers/scsi/lpfc/lpfc_init.c | 19 -- drivers/scsi/lpfc/lpfc_scsi.c | 83 ++------ drivers/scsi/qla2xxx/qla_def.h | 3 + drivers/scsi/qla2xxx/qla_init.c | 26 ++- drivers/scsi/qla2xxx/qla_os.c | 21 +- drivers/scsi/qla2xxx/qla_rscn.c | 3 +- drivers/scsi/scsi_transport_fc.c | 446 ++++++++++++++++++++++++--------------- include/scsi/scsi_transport_fc.h | 31 ++- 9 files changed, 384 insertions(+), 276 deletions(-) (limited to 'include') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 56052f4510c3..6c846ad373bc 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1028,6 +1028,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba, if (ndlp->nlp_type & NLP_FCP_INITIATOR) rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; + scsi_block_requests(phba->host); ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, @@ -1044,6 +1045,23 @@ lpfc_register_remote_port(struct lpfc_hba * phba, } rdata = rport->dd_data; rdata->pnode = ndlp; + scsi_unblock_requests(phba->host); + + return; +} + +static void +lpfc_unregister_remote_port(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp) +{ + struct fc_rport *rport = ndlp->rport; + struct lpfc_rport_data *rdata = rport->dd_data; + + ndlp->rport = NULL; + rdata->pnode = NULL; + scsi_block_requests(phba->host); + fc_remote_port_delete(rport); + scsi_unblock_requests(phba->host); return; } @@ -1260,7 +1278,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) * may have removed the remote port. */ if ((rport_del != none) && nlp->rport) - fc_remote_port_block(nlp->rport); + lpfc_unregister_remote_port(phba, nlp); if (rport_add != none) { /* @@ -1270,8 +1288,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) */ if (!nlp->rport) lpfc_register_remote_port(phba, nlp); - else - fc_remote_port_unblock(nlp->rport); /* * if we added to Mapped list, but the remote port @@ -1490,7 +1506,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) LPFC_MBOXQ_t *mb; LPFC_MBOXQ_t *nextmb; struct lpfc_dmabuf *mp; - struct fc_rport *rport; /* Cleanup node for NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, @@ -1507,10 +1522,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) * and flush cache's w/o generating flush errors. */ if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { - rport = ndlp->rport; - ndlp->rport = NULL; - fc_remote_port_unblock(rport); - fc_remote_port_delete(rport); + lpfc_unregister_remote_port(phba, ndlp); ndlp->nlp_sid = NLP_NO_SID; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 0856ff7d3b33..25d55f40424f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -537,12 +537,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba) lpfc_offline(phba); - /* - * Restart all traffic to this host. Since the fc_transport - * block functions (future) were not called in lpfc_offline, - * don't call them here. - */ - scsi_unblock_requests(phba->host); } } @@ -1226,12 +1220,6 @@ lpfc_online(struct lpfc_hba * phba) phba->fc_flag &= ~FC_OFFLINE_MODE; spin_unlock_irq(phba->host->host_lock); - /* - * Restart all traffic to this host. Since the fc_transport block - * functions (future) were not called in lpfc_offline, don't call them - * here. - */ - scsi_unblock_requests(phba->host); return 0; } @@ -1249,13 +1237,6 @@ lpfc_offline(struct lpfc_hba * phba) if (phba->fc_flag & FC_OFFLINE_MODE) return 0; - /* - * Don't call the fc_transport block api (future). The device is - * going offline and causing a timer to fire in the midlayer is - * unproductive. Just block all new requests until the driver - * comes back online. - */ - scsi_block_requests(phba->host); psli = &phba->sli; pring = &psli->ring[psli->fcp_ring]; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index b5ad1871d34b..c55ab1a630e5 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -403,14 +403,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, break; } - if (pnode) { - if (pnode->nlp_state != NLP_STE_MAPPED_NODE) - cmd->result = ScsiResult(DID_BUS_BUSY, - SAM_STAT_BUSY); - } - else { - cmd->result = ScsiResult(DID_NO_CONNECT, 0); - } + if ((pnode == NULL ) + || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) + cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY); } else { cmd->result = ScsiResult(DID_OK, 0); } @@ -539,7 +534,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba, struct lpfc_rport_data *rdata = scsi_dev->hostdata; struct lpfc_nodelist *ndlp = rdata->pnode; - if ((ndlp == 0) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { + if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { return 0; } @@ -727,39 +722,23 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) struct lpfc_rport_data *rdata = cmnd->device->hostdata; struct lpfc_nodelist *ndlp = rdata->pnode; struct lpfc_scsi_buf *lpfc_cmd = NULL; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; - int err = 0; + int err; - /* - * The target pointer is guaranteed not to be NULL because the driver - * only clears the device->hostdata field in lpfc_slave_destroy. This - * approach guarantees no further IO calls on this target. - */ - if (!ndlp) { - cmnd->result = ScsiResult(DID_NO_CONNECT, 0); + err = fc_remote_port_chkready(rport); + if (err) { + cmnd->result = err; goto out_fail_command; } /* - * A Fibre Channel target is present and functioning only when the node - * state is MAPPED. Any other state is a failure. + * Catch race where our node has transitioned, but the + * transport is still transitioning. */ - if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) { - if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) || - (ndlp->nlp_state == NLP_STE_UNUSED_NODE)) { - cmnd->result = ScsiResult(DID_NO_CONNECT, 0); - goto out_fail_command; - } - else if (ndlp->nlp_state == NLP_STE_NPR_NODE) { - cmnd->result = ScsiResult(DID_BUS_BUSY, 0); - goto out_fail_command; - } - /* - * The device is most likely recovered and the driver - * needs a bit more time to finish. Ask the midlayer - * to retry. - */ - goto out_host_busy; + if (!ndlp) { + cmnd->result = ScsiResult(DID_BUS_BUSY, 0); + goto out_fail_command; } list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); @@ -1163,44 +1142,16 @@ static int lpfc_slave_alloc(struct scsi_device *sdev) { struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0]; - struct lpfc_nodelist *ndlp = NULL; - int match = 0; struct lpfc_scsi_buf *scsi_buf = NULL; + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); uint32_t total = 0, i; uint32_t num_to_alloc = 0; unsigned long flags; - struct list_head *listp; - struct list_head *node_list[6]; - - /* - * Store the target pointer in the scsi_device hostdata pointer provided - * the driver has already discovered the target id. - */ - - /* Search the nlp lists other than unmap_list for this target ID */ - node_list[0] = &phba->fc_npr_list; - node_list[1] = &phba->fc_nlpmap_list; - node_list[2] = &phba->fc_prli_list; - node_list[3] = &phba->fc_reglogin_list; - node_list[4] = &phba->fc_adisc_list; - node_list[5] = &phba->fc_plogi_list; - - for (i = 0; i < 6 && !match; i++) { - listp = node_list[i]; - if (list_empty(listp)) - continue; - list_for_each_entry(ndlp, listp, nlp_listp) { - if ((sdev->id == ndlp->nlp_sid) && ndlp->rport) { - match = 1; - break; - } - } - } - if (!match) + if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - sdev->hostdata = ndlp->rport->dd_data; + sdev->hostdata = rport->dd_data; /* * Populate the cmds_per_lun count scsi_bufs into this host's globally diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index fc3234c3625b..7096945ea234 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -1665,6 +1666,8 @@ typedef struct fc_port { struct fc_rport *rport; u32 supported_classes; + struct work_struct rport_add_work; + struct work_struct rport_del_work; } fc_port_t; /* diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ce7e712ebe8d..290a6b92616c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1668,6 +1668,24 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) return (rval); } +static void +qla2x00_rport_add(void *data) +{ + fc_port_t *fcport = data; + + qla2x00_reg_remote_port(fcport->ha, fcport); +} + +static void +qla2x00_rport_del(void *data) +{ + fc_port_t *fcport = data; + + if (fcport->rport) + fc_remote_port_delete(fcport->rport); + fcport->rport = NULL; +} + /** * qla2x00_alloc_fcport() - Allocate a generic fcport. * @ha: HA context @@ -1693,6 +1711,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; + INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); + INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); return (fcport); } @@ -2056,8 +2076,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) struct fc_rport *rport; if (fcport->rport) { - fc_remote_port_unblock(fcport->rport); - return; + fc_remote_port_delete(fcport->rport); + fcport->rport = NULL; } rport_ids.node_name = wwn_to_u64(fcport->node_name); @@ -2071,7 +2091,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) "Unable to allocate fc remote port!\n"); return; } - rport->dd_data = fcport; + *((fc_port_t **)rport->dd_data) = fcport; rport->supported_classes = fcport->supported_classes; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b899282a856e..c58c9d97b041 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -348,11 +348,13 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; + struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); srb_t *sp; int rval; - if (!fcport) { - cmd->result = DID_NO_CONNECT << 16; + rval = fc_remote_port_chkready(rport); + if (rval) { + cmd->result = rval; goto qc_fail_command; } @@ -401,11 +403,13 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; + struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); srb_t *sp; int rval; - if (!fcport) { - cmd->result = DID_NO_CONNECT << 16; + rval = fc_remote_port_chkready(rport); + if (rval) { + cmd->result = rval; goto qc24_fail_command; } @@ -1041,10 +1045,10 @@ qla2xxx_slave_alloc(struct scsi_device *sdev) { struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); - if (!rport) + if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - sdev->hostdata = rport->dd_data; + sdev->hostdata = *(fc_port_t **)rport->dd_data; return 0; } @@ -1636,7 +1640,8 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, int do_login) { if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) - fc_remote_port_block(fcport->rport); + schedule_work(&fcport->rport_del_work); + /* * We may need to retry the login, so don't change the state of the * port but do the retries. @@ -1697,7 +1702,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) continue; if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) - fc_remote_port_block(fcport->rport); + schedule_work(&fcport->rport_del_work); atomic_set(&fcport->state, FCS_DEVICE_LOST); } } diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c index 3e53f62d640d..2c3342108dd8 100644 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ b/drivers/scsi/qla2xxx/qla_rscn.c @@ -320,8 +320,7 @@ qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat, fcport->flags &= ~FCF_FAILOVER_NEEDED; fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_ONLINE); - if (fcport->rport) - fc_remote_port_unblock(fcport->rport); + schedule_work(&fcport->rport_add_work); } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 27702097b7fc..ca098fc2a607 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -210,7 +210,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names) #define FC_MGMTSRVR_PORTID 0x00000a -static void fc_timeout_blocked_rport(void *data); +static void fc_timeout_deleted_rport(void *data); static void fc_scsi_scan_rport(void *data); static void fc_rport_terminate(struct fc_rport *rport); @@ -384,7 +384,9 @@ show_fc_rport_##field (struct class_device *cdev, char *buf) \ struct fc_rport *rport = transport_class_to_rport(cdev); \ struct Scsi_Host *shost = rport_to_shost(rport); \ struct fc_internal *i = to_fc_internal(shost->transportt); \ - if (i->f->get_rport_##field) \ + if ((i->f->get_rport_##field) && \ + !((rport->port_state == FC_PORTSTATE_BLOCKED) || \ + (rport->port_state == FC_PORTSTATE_NOTPRESENT))) \ i->f->get_rport_##field(rport); \ return snprintf(buf, sz, format_string, cast rport->field); \ } @@ -398,6 +400,9 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \ struct fc_rport *rport = transport_class_to_rport(cdev); \ struct Scsi_Host *shost = rport_to_shost(rport); \ struct fc_internal *i = to_fc_internal(shost->transportt); \ + if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \ + (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \ + return -EBUSY; \ val = simple_strtoul(buf, NULL, 0); \ i->f->set_rport_##field(rport, val); \ return count; \ @@ -500,7 +505,29 @@ static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO, /* Dynamic Remote Port Attributes */ -fc_rport_rw_attr(dev_loss_tmo, "%d\n", 20); +/* + * dev_loss_tmo attribute + */ +fc_rport_show_function(dev_loss_tmo, "%d\n", 20, ) +static ssize_t +store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf, + size_t count) +{ + int val; + struct fc_rport *rport = transport_class_to_rport(cdev); + struct Scsi_Host *shost = rport_to_shost(rport); + struct fc_internal *i = to_fc_internal(shost->transportt); + if ((rport->port_state == FC_PORTSTATE_BLOCKED) || + (rport->port_state == FC_PORTSTATE_NOTPRESENT)) + return -EBUSY; + val = simple_strtoul(buf, NULL, 0); + if ((val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)) + return -EINVAL; + i->f->set_rport_dev_loss_tmo(rport, val); + return count; +} +static FC_CLASS_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR, + show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo); /* Private Remote Port Attributes */ @@ -1214,6 +1241,25 @@ fc_remove_host(struct Scsi_Host *shost) } EXPORT_SYMBOL(fc_remove_host); +/* + * fc_rport_tgt_remove - Removes the scsi target on the remote port + * @rport: The remote port to be operated on + */ +static void +fc_rport_tgt_remove(struct fc_rport *rport) +{ + struct Scsi_Host *shost = rport_to_shost(rport); + + scsi_target_unblock(&rport->dev); + + /* Stop anything on the workq */ + if (!cancel_delayed_work(&rport->dev_loss_work)) + flush_scheduled_work(); + scsi_flush_work(shost); + + scsi_remove_target(&rport->dev); +} + /** * fc_rport_create - allocates and creates a remote FC port. * @shost: scsi host the remote port is connected to. @@ -1260,7 +1306,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel, rport->dd_data = &rport[1]; rport->channel = channel; - INIT_WORK(&rport->dev_loss_work, fc_timeout_blocked_rport, rport); + INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport); INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); spin_lock_irqsave(shost->host_lock, flags); @@ -1352,17 +1398,93 @@ struct fc_rport * fc_remote_port_add(struct Scsi_Host *shost, int channel, struct fc_rport_identifiers *ids) { + struct fc_internal *fci = to_fc_internal(shost->transportt); struct fc_rport *rport; unsigned long flags; int match = 0; + /* + * Search the list of "active" rports, for an rport that has been + * deleted, but we've held off the real delete while the target + * is in a "blocked" state. + */ + spin_lock_irqsave(shost->host_lock, flags); + + list_for_each_entry(rport, &fc_host_rports(shost), peers) { + + if ((rport->port_state == FC_PORTSTATE_BLOCKED) && + (rport->channel == channel)) { + + switch (fc_host_tgtid_bind_type(shost)) { + case FC_TGTID_BIND_BY_WWPN: + case FC_TGTID_BIND_NONE: + if (rport->port_name == ids->port_name) + match = 1; + break; + case FC_TGTID_BIND_BY_WWNN: + if (rport->node_name == ids->node_name) + match = 1; + break; + case FC_TGTID_BIND_BY_ID: + if (rport->port_id == ids->port_id) + match = 1; + break; + } + + if (match) { + struct work_struct *work = + &rport->dev_loss_work; + + memcpy(&rport->node_name, &ids->node_name, + sizeof(rport->node_name)); + memcpy(&rport->port_name, &ids->port_name, + sizeof(rport->port_name)); + rport->port_id = ids->port_id; + + rport->port_state = FC_PORTSTATE_ONLINE; + rport->roles = ids->roles; + + spin_unlock_irqrestore(shost->host_lock, flags); + + if (fci->f->dd_fcrport_size) + memset(rport->dd_data, 0, + fci->f->dd_fcrport_size); + + /* + * If we were blocked, we were a target. + * If no longer a target, we leave the timer + * running in case the port changes roles + * prior to the timer expiring. If the timer + * fires, the target will be torn down. + */ + if (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)) + return rport; + + /* restart the target */ + + /* + * Stop the target timer first. Take no action + * on the del_timer failure as the state + * machine state change will validate the + * transaction. + */ + if (!cancel_delayed_work(work)) + flush_scheduled_work(); + + /* initiate a scan of the target */ + scsi_queue_work(shost, &rport->scan_work); + + return rport; + } + } + } + + /* Search the bindings array */ if (likely((ids->roles & FC_RPORT_ROLE_FCP_TARGET) && (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE))) { /* search for a matching consistent binding */ - spin_lock_irqsave(shost->host_lock, flags); - list_for_each_entry(rport, &fc_host_rport_bindings(shost), peers) { if (rport->channel != channel) @@ -1392,8 +1514,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } } - spin_unlock_irqrestore(shost->host_lock, flags); - if (match) { memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name)); @@ -1403,6 +1523,12 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, rport->roles = ids->roles; rport->port_state = FC_PORTSTATE_ONLINE; + spin_unlock_irqrestore(shost->host_lock, flags); + + if (fci->f->dd_fcrport_size) + memset(rport->dd_data, 0, + fci->f->dd_fcrport_size); + if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) /* initiate a scan of the target */ scsi_queue_work(shost, &rport->scan_work); @@ -1411,6 +1537,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } } + spin_unlock_irqrestore(shost->host_lock, flags); + /* No consistent binding found - create new remote port entry */ rport = fc_rport_create(shost, channel, ids); @@ -1418,25 +1546,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } EXPORT_SYMBOL(fc_remote_port_add); -/* - * fc_rport_tgt_remove - Removes the scsi target on the remote port - * @rport: The remote port to be operated on - */ -static void -fc_rport_tgt_remove(struct fc_rport *rport) -{ - struct Scsi_Host *shost = rport_to_shost(rport); - - scsi_target_unblock(&rport->dev); - - /* Stop anything on the workq */ - if (!cancel_delayed_work(&rport->dev_loss_work)) - flush_scheduled_work(); - scsi_flush_work(shost); - - scsi_remove_target(&rport->dev); -} - /* * fc_rport_terminate - this routine tears down and deallocates a remote port. * @rport: The remote port to be terminated @@ -1470,24 +1579,44 @@ fc_rport_terminate(struct fc_rport *rport) * The LLDD calls this routine to notify the transport that a remote * port is no longer part of the topology. Note: Although a port * may no longer be part of the topology, it may persist in the remote - * ports displayed by the fc_host. This is done so that target id - * mappings (managed via the remote port structures), are always visible - * as long as the mapping is valid, regardless of port state, + * ports displayed by the fc_host. We do this under 2 conditions: + * - If the port was a scsi target, we delay its deletion by "blocking" it. + * This allows the port to temporarily disappear, then reappear without + * disrupting the SCSI device tree attached to it. During the "blocked" + * period the port will still exist. + * - If the port was a scsi target and disappears for longer than we + * expect, we'll delete the port and the tear down the SCSI device tree + * attached to it. However, we want to semi-persist the target id assigned + * to that port if it eventually does exist. The port structure will + * remain (although with minimal information) so that the target id + * bindings remails. * * If the remote port is not an FCP Target, it will be fully torn down * and deallocated, including the fc_remote_port class device. * - * If the remote port is an FCP Target, the port structure will be - * marked as Not Present, but will remain as long as there is a valid - * SCSI target id mapping associated with the port structure. Validity - * is determined by the binding type. If binding by wwpn, then the port - * structure is always valid and will not be deallocated until the host - * is removed. If binding by wwnn, then the port structure is valid - * until another port with the same node name is found in the topology. - * If binding by port id (fc address), then the port structure is valid - * valid until another port with the same address is identified. + * If the remote port is an FCP Target, the port will be placed in a + * temporary blocked state. From the LLDD's perspective, the rport no + * longer exists. From the SCSI midlayer's perspective, the SCSI target + * exists, but all sdevs on it are blocked from further I/O. The following + * is then expected: + * If the remote port does not return (signaled by a LLDD call to + * fc_remote_port_add()) within the dev_loss_tmo timeout, then the + * scsi target is removed - killing all outstanding i/o and removing the + * scsi devices attached ot it. The port structure will be marked Not + * Present and be partially cleared, leaving only enough information to + * recognize the remote port relative to the scsi target id binding if + * it later appears. The port will remain as long as there is a valid + * binding (e.g. until the user changes the binding type or unloads the + * scsi host with the binding). * - * Called from interrupt or normal process context. + * If the remote port returns within the dev_loss_tmo value (and matches + * according to the target id binding type), the port structure will be + * reused. If it is no longer a SCSI target, the target will be torn + * down. If it continues to be a SCSI target, then the target will be + * unblocked (allowing i/o to be resumed), and a scan will be activated + * to ensure that all luns are detected. + * + * Called from normal process context only - cannot be called from interrupt. * * Notes: * This routine assumes no locks are held on entry. @@ -1495,53 +1624,20 @@ fc_rport_terminate(struct fc_rport *rport) void fc_remote_port_delete(struct fc_rport *rport) { - struct Scsi_Host *shost = rport_to_shost(rport); - unsigned long flags; + int timeout = rport->dev_loss_tmo; - /* If no scsi target id mapping or consistent binding type, delete it */ - if ((rport->scsi_target_id == -1) || - (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE)) { + /* If no scsi target id mapping, delete it */ + if (rport->scsi_target_id == -1) { fc_rport_terminate(rport); return; } - fc_rport_tgt_remove(rport); - - spin_lock_irqsave(shost->host_lock, flags); - list_move_tail(&rport->peers, &fc_host_rport_bindings(shost)); - spin_unlock_irqrestore(shost->host_lock, flags); - - /* - * Note: We do not remove or clear the hostdata area. This allows - * host-specific target data to persist along with the - * scsi_target_id. It's up to the host to manage it's hostdata area. - */ + scsi_target_block(&rport->dev); - /* - * Reinitialize port attributes that may change if the port comes back. - */ - rport->maxframe_size = -1; - rport->supported_classes = FC_COS_UNSPECIFIED; - rport->roles = FC_RPORT_ROLE_UNKNOWN; - rport->port_state = FC_PORTSTATE_NOTPRESENT; + /* cap the length the devices can be blocked until they are deleted */ + schedule_delayed_work(&rport->dev_loss_work, timeout * HZ); - /* remove the identifiers that aren't used in the consisting binding */ - switch (fc_host_tgtid_bind_type(shost)) { - case FC_TGTID_BIND_BY_WWPN: - rport->node_name = -1; - rport->port_id = -1; - break; - case FC_TGTID_BIND_BY_WWNN: - rport->port_name = -1; - rport->port_id = -1; - break; - case FC_TGTID_BIND_BY_ID: - rport->node_name = -1; - rport->port_name = -1; - break; - case FC_TGTID_BIND_NONE: /* to keep compiler happy */ - break; - } + rport->port_state = FC_PORTSTATE_BLOCKED; } EXPORT_SYMBOL(fc_remote_port_delete); @@ -1574,127 +1670,140 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) unsigned long flags; int create = 0; - rport->roles = roles; - spin_lock_irqsave(shost->host_lock, flags); - if ((rport->scsi_target_id == -1) && - (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { - rport->scsi_target_id = fc_host->next_target_id++; - create = 1; + if (roles & FC_RPORT_ROLE_FCP_TARGET) { + if (rport->scsi_target_id == -1) { + rport->scsi_target_id = fc_host->next_target_id++; + create = 1; + } else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) + create = 1; } spin_unlock_irqrestore(shost->host_lock, flags); - if (create) + rport->roles = roles; + + if (create) { + /* + * There may have been a delete timer running on the + * port. Ensure that it is cancelled as we now know + * the port is an FCP Target. + * Note: we know the rport is exists and in an online + * state as the LLDD would not have had an rport + * reference to pass us. + * + * Take no action on the del_timer failure as the state + * machine state change will validate the + * transaction. + */ + if (!cancel_delayed_work(&rport->dev_loss_work)) + flush_scheduled_work(); + /* initiate a scan of the target */ scsi_queue_work(shost, &rport->scan_work); + } } EXPORT_SYMBOL(fc_remote_port_rolechg); /** - * fc_timeout_blocked_rport - Timeout handler for blocked remote port - * that fails to return in the alloted time. - * @data: scsi target that failed to reappear in the alloted time. + * fc_timeout_deleted_rport - Timeout handler for a deleted remote port that + * was a SCSI target (thus was blocked), and failed + * to return in the alloted time. + * + * @data: rport target that failed to reappear in the alloted time. **/ static void -fc_timeout_blocked_rport(void *data) +fc_timeout_deleted_rport(void *data) { struct fc_rport *rport = (struct fc_rport *)data; + struct Scsi_Host *shost = rport_to_shost(rport); + unsigned long flags; - rport->port_state = FC_PORTSTATE_OFFLINE; - - dev_printk(KERN_ERR, &rport->dev, - "blocked FC remote port time out: removing target\n"); + spin_lock_irqsave(shost->host_lock, flags); /* - * As this only occurs if the remote port (scsi target) - * went away and didn't come back - we'll remove - * all attached scsi devices. + * If the port is ONLINE, then it came back, but was no longer an + * FCP target. Thus we need to tear down the scsi_target on it. */ - scsi_target_unblock(&rport->dev); - scsi_remove_target(&rport->dev); -} + if (rport->port_state == FC_PORTSTATE_ONLINE) { + spin_unlock_irqrestore(shost->host_lock, flags); -/** - * fc_remote_port_block - temporarily block any scsi traffic to a remote port. - * @rport: remote port to be blocked. - * - * scsi lldd's with a FC transport call this routine to temporarily stop - * all scsi traffic to a remote port. If the port is not a SCSI target, - * no action is taken. If the port is a SCSI target, all attached devices - * are placed into a SDEV_BLOCK state and a timer is started. The timer is - * represents the maximum amount of time the port may be blocked. If the - * timer expires, the port is considered non-existent and the attached - * scsi devices will be removed. - * - * Called from interrupt or normal process context. - * - * Returns zero if successful or error if not - * - * Notes: - * This routine assumes no locks are held on entry. - * - * The timeout and timer types are extracted from the fc transport - * attributes from the caller's rport pointer. - **/ -int -fc_remote_port_block(struct fc_rport *rport) -{ - int timeout = rport->dev_loss_tmo; - struct work_struct *work = &rport->dev_loss_work; + dev_printk(KERN_ERR, &rport->dev, + "blocked FC remote port time out: removing target\n"); - if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) - return -EINVAL; + fc_rport_tgt_remove(rport); - scsi_target_block(&rport->dev); + return; + } - /* cap the length the devices can be blocked */ - schedule_delayed_work(work, timeout * HZ); + if (rport->port_state != FC_PORTSTATE_BLOCKED) { + spin_unlock_irqrestore(shost->host_lock, flags); + dev_printk(KERN_ERR, &rport->dev, + "blocked FC remote port time out: leaving target alone\n"); + return; + } - rport->port_state = FC_PORTSTATE_BLOCKED; - return 0; -} -EXPORT_SYMBOL(fc_remote_port_block); + if (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE) { + spin_unlock_irqrestore(shost->host_lock, flags); + dev_printk(KERN_ERR, &rport->dev, + "blocked FC remote port time out: removing target\n"); + fc_rport_terminate(rport); + return; + } -/** - * fc_remote_port_unblock - restart any blocked scsi traffic to a remote port. - * @rport: remote port to be unblocked. - * - * scsi lld's with a FC transport call this routine to restart IO to all - * devices associated with the caller's scsi target following a fc_target_block - * request. Called from interrupt or normal process context. - * - * Notes: - * This routine assumes no locks are held on entry. - **/ - void -fc_remote_port_unblock(struct fc_rport *rport) -{ - struct work_struct *work = &rport->dev_loss_work; - struct Scsi_Host *shost = rport_to_shost(rport); + dev_printk(KERN_ERR, &rport->dev, + "blocked FC remote port time out: removing target and " + "saving binding\n"); + + list_move_tail(&rport->peers, &fc_host_rport_bindings(shost)); /* - * Stop the target timer first. Take no action on the del_timer - * failure as the state machine state change will validate the - * transaction. + * Note: We do not remove or clear the hostdata area. This allows + * host-specific target data to persist along with the + * scsi_target_id. It's up to the host to manage it's hostdata area. */ - if (!cancel_delayed_work(work)) - flush_scheduled_work(); - if (rport->port_state == FC_PORTSTATE_OFFLINE) - /* - * initiate a scan of the target as the target has - * been torn down. - */ - scsi_queue_work(shost, &rport->scan_work); - else - scsi_target_unblock(&rport->dev); + /* + * Reinitialize port attributes that may change if the port comes back. + */ + rport->maxframe_size = -1; + rport->supported_classes = FC_COS_UNSPECIFIED; + rport->roles = FC_RPORT_ROLE_UNKNOWN; + rport->port_state = FC_PORTSTATE_NOTPRESENT; - rport->port_state = FC_PORTSTATE_ONLINE; + /* remove the identifiers that aren't used in the consisting binding */ + switch (fc_host_tgtid_bind_type(shost)) { + case FC_TGTID_BIND_BY_WWPN: + rport->node_name = -1; + rport->port_id = -1; + break; + case FC_TGTID_BIND_BY_WWNN: + rport->port_name = -1; + rport->port_id = -1; + break; + case FC_TGTID_BIND_BY_ID: + rport->node_name = -1; + rport->port_name = -1; + break; + case FC_TGTID_BIND_NONE: /* to keep compiler happy */ + break; + } + + spin_unlock_irqrestore(shost->host_lock, flags); + + /* + * As this only occurs if the remote port (scsi target) + * went away and didn't come back - we'll remove + * all attached scsi devices. + */ + fc_rport_tgt_remove(rport); } -EXPORT_SYMBOL(fc_remote_port_unblock); /** * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. + * + * Will unblock the target (in case it went away and has now come back), + * then invoke a scan. + * * @data: remote port to be scanned. **/ static void @@ -1702,6 +1811,7 @@ fc_scsi_scan_rport(void *data) { struct fc_rport *rport = (struct fc_rport *)data; + scsi_target_unblock(&rport->dev); scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, SCAN_WILD_CARD, 1); } diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 4496b32972e5..319ff7a60dfe 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -28,6 +28,7 @@ #define SCSI_TRANSPORT_FC_H #include +#include struct scsi_transport_template; @@ -429,6 +430,34 @@ struct fc_function_template { }; +/** + * fc_remote_port_chkready - called to validate the remote port state + * prior to initiating io to the port. + * + * Returns a scsi result code that can be returned by the LLDD. + * + * @rport: remote port to be checked + **/ +static inline int +fc_remote_port_chkready(struct fc_rport *rport) +{ + int result; + + switch (rport->port_state) { + case FC_PORTSTATE_ONLINE: + result = 0; + break; + case FC_PORTSTATE_BLOCKED: + result = DID_BUS_BUSY << 16; + break; + default: + result = DID_NO_CONNECT << 16; + break; + } + return result; +} + + struct scsi_transport_template *fc_attach_transport( struct fc_function_template *); void fc_release_transport(struct scsi_transport_template *); @@ -437,8 +466,6 @@ struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost, int channel, struct fc_rport_identifiers *ids); void fc_remote_port_delete(struct fc_rport *rport); void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles); -int fc_remote_port_block(struct fc_rport *rport); -void fc_remote_port_unblock(struct fc_rport *rport); int scsi_is_fc_rport(const struct device *); static inline u64 wwn_to_u64(u8 *wwn) -- cgit v1.2.3 From 631bb0e74e811e0d9ad23e7462a02d4767b4dd9d Mon Sep 17 00:00:00 2001 From: Bob Picco Date: Mon, 31 Oct 2005 13:25:25 -0500 Subject: [IA64] Recent SPARSEMEM and DISCONTIG changes break some builds My only objection to pfn_to_kaddr, which was introduced for HotPlug memory, is that all arches have an identical implementation. I haven't had a chance to pursue why yet. There is probably some arch issue I'm unaware of. Signed-off-by: Bob Picco Signed-off-by: Tony Luck --- include/asm-ia64/page.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index ef436b9d06ad..9d41548b7fef 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -120,6 +120,7 @@ extern unsigned long max_low_pfn; #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) typedef union ia64_va { struct { -- cgit v1.2.3 From 2df5e8bcca53e528a78ee0e3b114d0d21dd6d043 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sat, 29 Oct 2005 17:51:31 +1000 Subject: powerpc: merge uaccess.h There is still a bug to be fixed and more merging to be done. Signed-off-by: Stephen Rothwell --- include/asm-powerpc/uaccess.h | 504 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/uaccess.h | 393 -------------------------------- include/asm-ppc64/uaccess.h | 341 ---------------------------- 3 files changed, 504 insertions(+), 734 deletions(-) create mode 100644 include/asm-powerpc/uaccess.h delete mode 100644 include/asm-ppc/uaccess.h delete mode 100644 include/asm-ppc64/uaccess.h (limited to 'include') diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h new file mode 100644 index 000000000000..2ecc3e16e49e --- /dev/null +++ b/include/asm-powerpc/uaccess.h @@ -0,0 +1,504 @@ +#ifndef _ARCH_POWERPC_UACCESS_H +#define _ARCH_POWERPC_UACCESS_H + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +#include +#include +#include + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + * + * The fs/ds values are now the highest legal address in the "segment". + * This simplifies the checking in the routines below. + */ + +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + +#ifdef __powerpc64__ +#define KERNEL_DS MAKE_MM_SEG(0UL) +#define USER_DS MAKE_MM_SEG(0xf000000000000000UL) +#else +#define KERNEL_DS MAKE_MM_SEG(~0UL) +#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) +#endif + +#define get_ds() (KERNEL_DS) +#define get_fs() (current->thread.fs) +#define set_fs(val) (current->thread.fs = (val)) + +#define segment_eq(a, b) ((a).seg == (b).seg) + +#ifdef __powerpc64__ +/* + * Use the alpha trick for checking ranges: + * + * Is a address valid? This does a straightforward calculation rather + * than tests. + * + * Address valid if: + * - "addr" doesn't have any high-bits set + * - AND "size" doesn't have any high-bits set + * - OR we are in kernel mode. + * + * We dont have to check for high bits in (addr+size) because the first + * two checks force the maximum result to be below the start of the + * kernel region. + */ +#define __access_ok(addr, size, segment) \ + (((segment).seg & (addr | size )) == 0) + +#else + +#define __access_ok(addr, size, segment) \ + (((addr) <= (segment).seg) && \ + (((size) == 0) || (((size) - 1) <= ((segment).seg - (addr))))) + +#endif + +#define access_ok(type, addr, size) \ + (__chk_user_ptr(addr), \ + __access_ok((__force unsigned long)(addr), (size), get_fs())) + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry { + unsigned long insn; + unsigned long fixup; +}; + +/* + * These are the main single-value transfer routines. They automatically + * use the right size if we just have the right pointer type. + * + * This gets kind of ugly. We want to return _two_ values in "get_user()" + * and yet we don't want to do any pointers, because that is too much + * of a performance impact. Thus we have a few rather ugly macros here, + * and hide all the ugliness from the user. + * + * The "__xxx" versions of the user access functions are versions that + * do not verify the address space, that must have been done previously + * with a separate "access_ok()" call (this is used when we do multiple + * accesses to the same area of user memory). + * + * As we use the same address space for kernel and user data on the + * PowerPC, we can just do these as direct assignments. (Of course, the + * exception handling means that it's no longer "just"...) + * + * The "user64" versions of the user access functions are versions that + * allow access of 64-bit data. The "get_user" functions do not + * properly handle 64-bit data because the value gets down cast to a long. + * The "put_user" functions already handle 64-bit data properly but we add + * "user64" versions for completeness + */ +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) +#define put_user(x, ptr) \ + __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) +#define __put_user(x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#ifndef __powerpc64__ +#define __get_user64(x, ptr) \ + __get_user64_nocheck((x), (ptr), sizeof(*(ptr))) +#define __put_user64(x, ptr) __put_user(x, ptr) +#endif + +#ifdef __powerpc64__ +#define __get_user_unaligned __get_user +#define __put_user_unaligned __put_user +#endif + +extern long __put_user_bad(void); + +#ifdef __powerpc64__ +#define __EX_TABLE_ALIGN "3" +#define __EX_TABLE_TYPE "llong" +#else +#define __EX_TABLE_ALIGN "2" +#define __EX_TABLE_TYPE "long" +#endif + +/* + * We don't tell gcc that we are accessing memory, but this is OK + * because we do not write to any memory gcc knows about, so there + * are no aliasing issues. + */ +#define __put_user_asm(x, addr, err, op) \ + __asm__ __volatile__( \ + "1: " op " %1,0(%2) # put_user\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,%3\n" \ + " b 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align " __EX_TABLE_ALIGN "\n" \ + " ."__EX_TABLE_TYPE" 1b,3b\n" \ + ".previous" \ + : "=r" (err) \ + : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) + +#ifndef __powerpc64__ +#define __put_user_asm2(x, addr, err) \ + __asm__ __volatile__( \ + "1: stw %1,0(%2)\n" \ + "2: stw %1+1,4(%2)\n" \ + "3:\n" \ + ".section .fixup,\"ax\"\n" \ + "4: li %0,%3\n" \ + " b 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align " __EX_TABLE_ALIGN "\n" \ + " ." __EX_TABLE_TYPE " 1b,4b\n" \ + " ." __EX_TABLE_TYPE " 2b,4b\n" \ + ".previous" \ + : "=r" (err) \ + : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) +#else /* __powerpc64__ */ +#define __put_user_asm2(x, ptr, retval) \ + __put_user_asm(x, ptr, retval, "std") +#endif /* __powerpc64__ */ + +#define __put_user_size(x, ptr, size, retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x, ptr, retval, "stb"); break; \ + case 2: __put_user_asm(x, ptr, retval, "sth"); break; \ + case 4: __put_user_asm(x, ptr, retval, "stw"); break; \ + case 8: __put_user_asm2(x, ptr, retval); break; \ + default: __put_user_bad(); \ + } \ +} while (0) + +#define __put_user_nocheck(x, ptr, size) \ +({ \ + long __pu_err; \ + might_sleep(); \ + __chk_user_ptr(ptr); \ + __put_user_size((x), (ptr), (size), __pu_err); \ + __pu_err; \ +}) + +#define __put_user_check(x, ptr, size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + might_sleep(); \ + if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ + __pu_err; \ +}) + +extern long __get_user_bad(void); + +#define __get_user_asm(x, addr, err, op) \ + __asm__ __volatile__( \ + "1: "op" %1,0(%2) # get_user\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,%3\n" \ + " li %1,0\n" \ + " b 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align "__EX_TABLE_ALIGN "\n" \ + " ." __EX_TABLE_TYPE " 1b,3b\n" \ + ".previous" \ + : "=r" (err), "=r" (x) \ + : "b" (addr), "i" (-EFAULT), "0" (err)) + +#ifndef __powerpc64__ +#define __get_user_asm2(x, addr, err) \ + __asm__ __volatile__( \ + "1: lwz %1,0(%2)\n" \ + "2: lwz %1+1,4(%2)\n" \ + "3:\n" \ + ".section .fixup,\"ax\"\n" \ + "4: li %0,%3\n" \ + " li %1,0\n" \ + " li %1+1,0\n" \ + " b 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align " __EX_TABLE_ALIGN "\n" \ + " ." __EX_TABLE_TYPE " 1b,4b\n" \ + " ." __EX_TABLE_TYPE " 2b,4b\n" \ + ".previous" \ + : "=r" (err), "=&r" (x) \ + : "b" (addr), "i" (-EFAULT), "0" (err)) +#else +#define __get_user_asm2(x, addr, err) \ + __get_user_asm(x, addr, err, "ld") +#endif /* __powerpc64__ */ + +#define __get_user_size(x, ptr, size, retval) \ +do { \ + retval = 0; \ + __chk_user_ptr(ptr); \ + if (size > sizeof(x)) \ + (x) = __get_user_bad(); \ + switch (size) { \ + case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \ + case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \ + case 4: __get_user_asm(x, ptr, retval, "lwz"); break; \ + case 8: __get_user_asm2(x, ptr, retval); break; \ + default: (x) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_nocheck(x, ptr, size) \ +({ \ + long __gu_err; \ + unsigned long __gu_val; \ + __chk_user_ptr(ptr); \ + might_sleep(); \ + __get_user_size(__gu_val, (ptr), (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#ifndef __powerpc64__ +#define __get_user64_nocheck(x, ptr, size) \ +({ \ + long __gu_err; \ + long long __gu_val; \ + __chk_user_ptr(ptr); \ + might_sleep(); \ + __get_user_size(__gu_val, (ptr), (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) +#endif /* __powerpc64__ */ + +#define __get_user_check(x, ptr, size) \ +({ \ + long __gu_err = -EFAULT; \ + unsigned long __gu_val = 0; \ + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + might_sleep(); \ + if (access_ok(VERIFY_READ, __gu_addr, (size))) \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +/* more complex routines */ + +extern unsigned long __copy_tofrom_user(void __user *to, + const void __user *from, unsigned long size); + +#ifndef __powerpc64__ +extern inline unsigned long +copy_from_user(void *to, const void __user *from, unsigned long n) +{ + unsigned long over; + + if (access_ok(VERIFY_READ, from, n)) + return __copy_tofrom_user((__force void __user *)to, from, n); + if ((unsigned long)from < TASK_SIZE) { + over = (unsigned long)from + n - TASK_SIZE; + return __copy_tofrom_user((__force void __user *)to, from, + n - over) + over; + } + return n; +} + +extern inline unsigned long +copy_to_user(void __user *to, const void *from, unsigned long n) +{ + unsigned long over; + + if (access_ok(VERIFY_WRITE, to, n)) + return __copy_tofrom_user(to, (__force void __user *)from, n); + if ((unsigned long)to < TASK_SIZE) { + over = (unsigned long)to + n - TASK_SIZE; + return __copy_tofrom_user(to, (__force void __user *)from, + n - over) + over; + } + return n; +} + +#else /* __powerpc64__ */ + +static inline unsigned long +__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) +{ + if (__builtin_constant_p(n) && (n <= 8)) { + unsigned long ret; + + switch (n) { + case 1: + __get_user_size(*(u8 *)to, from, 1, ret); + break; + case 2: + __get_user_size(*(u16 *)to, from, 2, ret); + break; + case 4: + __get_user_size(*(u32 *)to, from, 4, ret); + break; + case 8: + __get_user_size(*(u64 *)to, from, 8, ret); + break; + } + return (ret == -EFAULT) ? n : 0; + } + return __copy_tofrom_user((__force void __user *) to, from, n); +} + +static inline unsigned long +__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) +{ + if (__builtin_constant_p(n) && (n <= 8)) { + unsigned long ret; + + switch (n) { + case 1: + __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret); + break; + case 2: + __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret); + break; + case 4: + __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret); + break; + case 8: + __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret); + break; + } + return (ret == -EFAULT) ? n : 0; + } + return __copy_tofrom_user(to, (__force const void __user *) from, n); +} + +#endif /* __powerpc64__ */ + +static inline unsigned long +__copy_from_user(void *to, const void __user *from, unsigned long size) +{ + might_sleep(); +#ifndef __powerpc64__ + return __copy_tofrom_user((__force void __user *)to, from, size); +#else /* __powerpc64__ */ + return __copy_from_user_inatomic(to, from, size); +#endif /* __powerpc64__ */ +} + +static inline unsigned long +__copy_to_user(void __user *to, const void *from, unsigned long size) +{ + might_sleep(); +#ifndef __powerpc64__ + return __copy_tofrom_user(to, (__force void __user *)from, size); +#else /* __powerpc64__ */ + return __copy_to_user_inatomic(to, from, size); +#endif /* __powerpc64__ */ +} + +#ifndef __powerpc64__ +#define __copy_to_user_inatomic __copy_to_user +#define __copy_from_user_inatomic __copy_from_user +#else /* __powerpc64__ */ +#define __copy_in_user(to, from, size) \ + __copy_tofrom_user((to), (from), (size)) + +extern unsigned long copy_from_user(void *to, const void __user *from, + unsigned long n); +extern unsigned long copy_to_user(void __user *to, const void *from, + unsigned long n); +extern unsigned long copy_in_user(void __user *to, const void __user *from, + unsigned long n); +#endif /* __powerpc64__ */ + +extern unsigned long __clear_user(void __user *addr, unsigned long size); + +static inline unsigned long clear_user(void __user *addr, unsigned long size) +{ + might_sleep(); + if (likely(access_ok(VERIFY_WRITE, addr, size))) + return __clear_user(addr, size); +#ifndef __powerpc64__ + if ((unsigned long)addr < TASK_SIZE) { + unsigned long over = (unsigned long)addr + size - TASK_SIZE; + return __clear_user(addr, size - over) + over; + } +#endif /* __powerpc64__ */ + return size; +} + +extern int __strncpy_from_user(char *dst, const char __user *src, long count); + +static inline long strncpy_from_user(char *dst, const char __user *src, + long count) +{ + might_sleep(); + if (likely(access_ok(VERIFY_READ, src, 1))) + return __strncpy_from_user(dst, src, count); + return -EFAULT; +} + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 for error + */ +#ifndef __powerpc64__ +extern int __strnlen_user(const char __user *str, long len, unsigned long top); +#else /* __powerpc64__ */ +extern int __strnlen_user(const char __user *str, long len); +#endif /* __powerpc64__ */ + +/* + * Returns the length of the string at str (including the null byte), + * or 0 if we hit a page we can't access, + * or something > len if we didn't find a null byte. + * + * The `top' parameter to __strnlen_user is to make sure that + * we can never overflow from the user area into kernel space. + */ +static inline int strnlen_user(const char __user *str, long len) +{ +#ifndef __powerpc64__ + unsigned long top = current->thread.fs.seg; + + if ((unsigned long)str > top) + return 0; + return __strnlen_user(str, len, top); +#else /* __powerpc64__ */ + might_sleep(); + if (likely(access_ok(VERIFY_READ, str, 1))) + return __strnlen_user(str, len); + return 0; +#endif /* __powerpc64__ */ +} + +#define strlen_user(str) strnlen_user((str), 0x7ffffffe) + +#endif /* __ASSEMBLY__ */ +#endif /* __KERNEL__ */ + +#endif /* _ARCH_POWERPC_UACCESS_H */ diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h deleted file mode 100644 index 63f56224da8c..000000000000 --- a/include/asm-ppc/uaccess.h +++ /dev/null @@ -1,393 +0,0 @@ -#ifdef __KERNEL__ -#ifndef _PPC_UACCESS_H -#define _PPC_UACCESS_H - -#ifndef __ASSEMBLY__ -#include -#include -#include - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons, these macros are grossly misnamed. - * - * The fs/ds values are now the highest legal address in the "segment". - * This simplifies the checking in the routines below. - */ - -#define KERNEL_DS ((mm_segment_t) { ~0UL }) -#define USER_DS ((mm_segment_t) { TASK_SIZE - 1 }) - -#define get_ds() (KERNEL_DS) -#define get_fs() (current->thread.fs) -#define set_fs(val) (current->thread.fs = (val)) - -#define segment_eq(a,b) ((a).seg == (b).seg) - -#define __access_ok(addr,size) \ - ((addr) <= current->thread.fs.seg \ - && ((size) == 0 || (size) - 1 <= current->thread.fs.seg - (addr))) - -#define access_ok(type, addr, size) \ - (__chk_user_ptr(addr),__access_ok((unsigned long)(addr),(size))) - -/* - * The exception table consists of pairs of addresses: the first is the - * address of an instruction that is allowed to fault, and the second is - * the address at which the program should continue. No registers are - * modified, so it is entirely up to the continuation code to figure out - * what to do. - * - * All the routines below use bits of fixup code that are out of line - * with the main instruction path. This means when everything is well, - * we don't even have to jump over them. Further, they do not intrude - * on our cache or tlb entries. - */ - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -/* - * These are the main single-value transfer routines. They automatically - * use the right size if we just have the right pointer type. - * - * This gets kind of ugly. We want to return _two_ values in "get_user()" - * and yet we don't want to do any pointers, because that is too much - * of a performance impact. Thus we have a few rather ugly macros here, - * and hide all the ugliness from the user. - * - * The "__xxx" versions of the user access functions are versions that - * do not verify the address space, that must have been done previously - * with a separate "access_ok()" call (this is used when we do multiple - * accesses to the same area of user memory). - * - * As we use the same address space for kernel and user data on the - * PowerPC, we can just do these as direct assignments. (Of course, the - * exception handling means that it's no longer "just"...) - * - * The "user64" versions of the user access functions are versions that - * allow access of 64-bit data. The "get_user" functions do not - * properly handle 64-bit data because the value gets down cast to a long. - * The "put_user" functions already handle 64-bit data properly but we add - * "user64" versions for completeness - */ -#define get_user(x,ptr) \ - __get_user_check((x),(ptr),sizeof(*(ptr))) -#define get_user64(x,ptr) \ - __get_user64_check((x),(ptr),sizeof(*(ptr))) -#define put_user(x,ptr) \ - __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -#define put_user64(x,ptr) put_user(x,ptr) - -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) -#define __get_user64(x,ptr) \ - __get_user64_nocheck((x),(ptr),sizeof(*(ptr))) -#define __put_user(x,ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -#define __put_user64(x,ptr) __put_user(x,ptr) - -extern long __put_user_bad(void); - -#define __put_user_nocheck(x,ptr,size) \ -({ \ - long __pu_err; \ - __chk_user_ptr(ptr); \ - __put_user_size((x),(ptr),(size),__pu_err); \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ - __pu_err; \ -}) - -#define __put_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: \ - __put_user_asm(x, ptr, retval, "stb"); \ - break; \ - case 2: \ - __put_user_asm(x, ptr, retval, "sth"); \ - break; \ - case 4: \ - __put_user_asm(x, ptr, retval, "stw"); \ - break; \ - case 8: \ - __put_user_asm2(x, ptr, retval); \ - break; \ - default: \ - __put_user_bad(); \ - } \ -} while (0) - -/* - * We don't tell gcc that we are accessing memory, but this is OK - * because we do not write to any memory gcc knows about, so there - * are no aliasing issues. - */ -#define __put_user_asm(x, addr, err, op) \ - __asm__ __volatile__( \ - "1: "op" %1,0(%2)\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%3\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".previous" \ - : "=r" (err) \ - : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) - -#define __put_user_asm2(x, addr, err) \ - __asm__ __volatile__( \ - "1: stw %1,0(%2)\n" \ - "2: stw %1+1,4(%2)\n" \ - "3:\n" \ - ".section .fixup,\"ax\"\n" \ - "4: li %0,%3\n" \ - " b 3b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,4b\n" \ - " .long 2b,4b\n" \ - ".previous" \ - : "=r" (err) \ - : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) - -#define __get_user_nocheck(x, ptr, size) \ -({ \ - long __gu_err; \ - unsigned long __gu_val; \ - __chk_user_ptr(ptr); \ - __get_user_size(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user64_nocheck(x, ptr, size) \ -({ \ - long __gu_err; \ - long long __gu_val; \ - __chk_user_ptr(ptr); \ - __get_user_size64(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_check(x, ptr, size) \ -({ \ - long __gu_err = -EFAULT; \ - unsigned long __gu_val = 0; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - if (access_ok(VERIFY_READ, __gu_addr, (size))) \ - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user64_check(x, ptr, size) \ -({ \ - long __gu_err = -EFAULT; \ - long long __gu_val = 0; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - if (access_ok(VERIFY_READ, __gu_addr, (size))) \ - __get_user_size64(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -extern long __get_user_bad(void); - -#define __get_user_size(x, ptr, size, retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: \ - __get_user_asm(x, ptr, retval, "lbz"); \ - break; \ - case 2: \ - __get_user_asm(x, ptr, retval, "lhz"); \ - break; \ - case 4: \ - __get_user_asm(x, ptr, retval, "lwz"); \ - break; \ - default: \ - x = __get_user_bad(); \ - } \ -} while (0) - -#define __get_user_size64(x, ptr, size, retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: \ - __get_user_asm(x, ptr, retval, "lbz"); \ - break; \ - case 2: \ - __get_user_asm(x, ptr, retval, "lhz"); \ - break; \ - case 4: \ - __get_user_asm(x, ptr, retval, "lwz"); \ - break; \ - case 8: \ - __get_user_asm2(x, ptr, retval); \ - break; \ - default: \ - x = __get_user_bad(); \ - } \ -} while (0) - -#define __get_user_asm(x, addr, err, op) \ - __asm__ __volatile__( \ - "1: "op" %1,0(%2)\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%3\n" \ - " li %1,0\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".previous" \ - : "=r"(err), "=r"(x) \ - : "b"(addr), "i"(-EFAULT), "0"(err)) - -#define __get_user_asm2(x, addr, err) \ - __asm__ __volatile__( \ - "1: lwz %1,0(%2)\n" \ - "2: lwz %1+1,4(%2)\n" \ - "3:\n" \ - ".section .fixup,\"ax\"\n" \ - "4: li %0,%3\n" \ - " li %1,0\n" \ - " li %1+1,0\n" \ - " b 3b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,4b\n" \ - " .long 2b,4b\n" \ - ".previous" \ - : "=r"(err), "=&r"(x) \ - : "b"(addr), "i"(-EFAULT), "0"(err)) - -/* more complex routines */ - -extern int __copy_tofrom_user(void __user *to, const void __user *from, - unsigned long size); - -extern inline unsigned long -copy_from_user(void *to, const void __user *from, unsigned long n) -{ - unsigned long over; - - if (access_ok(VERIFY_READ, from, n)) - return __copy_tofrom_user((__force void __user *)to, from, n); - if ((unsigned long)from < TASK_SIZE) { - over = (unsigned long)from + n - TASK_SIZE; - return __copy_tofrom_user((__force void __user *)to, from, n - over) + over; - } - return n; -} - -extern inline unsigned long -copy_to_user(void __user *to, const void *from, unsigned long n) -{ - unsigned long over; - - if (access_ok(VERIFY_WRITE, to, n)) - return __copy_tofrom_user(to, (__force void __user *) from, n); - if ((unsigned long)to < TASK_SIZE) { - over = (unsigned long)to + n - TASK_SIZE; - return __copy_tofrom_user(to, (__force void __user *) from, n - over) + over; - } - return n; -} - -static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long size) -{ - return __copy_tofrom_user((__force void __user *)to, from, size); -} - -static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long size) -{ - return __copy_tofrom_user(to, (__force void __user *)from, size); -} - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -extern unsigned long __clear_user(void __user *addr, unsigned long size); - -extern inline unsigned long -clear_user(void __user *addr, unsigned long size) -{ - if (access_ok(VERIFY_WRITE, addr, size)) - return __clear_user(addr, size); - if ((unsigned long)addr < TASK_SIZE) { - unsigned long over = (unsigned long)addr + size - TASK_SIZE; - return __clear_user(addr, size - over) + over; - } - return size; -} - -extern int __strncpy_from_user(char *dst, const char __user *src, long count); - -extern inline long -strncpy_from_user(char *dst, const char __user *src, long count) -{ - if (access_ok(VERIFY_READ, src, 1)) - return __strncpy_from_user(dst, src, count); - return -EFAULT; -} - -/* - * Return the size of a string (including the ending 0) - * - * Return 0 for error - */ - -extern int __strnlen_user(const char __user *str, long len, unsigned long top); - -/* - * Returns the length of the string at str (including the null byte), - * or 0 if we hit a page we can't access, - * or something > len if we didn't find a null byte. - * - * The `top' parameter to __strnlen_user is to make sure that - * we can never overflow from the user area into kernel space. - */ -extern __inline__ int strnlen_user(const char __user *str, long len) -{ - unsigned long top = current->thread.fs.seg; - - if ((unsigned long)str > top) - return 0; - return __strnlen_user(str, len, top); -} - -#define strlen_user(str) strnlen_user((str), 0x7ffffffe) - -#endif /* __ASSEMBLY__ */ - -#endif /* _PPC_UACCESS_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h deleted file mode 100644 index 132c1276547b..000000000000 --- a/include/asm-ppc64/uaccess.h +++ /dev/null @@ -1,341 +0,0 @@ -#ifndef _PPC64_UACCESS_H -#define _PPC64_UACCESS_H - -/* - * 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. - */ - -#ifndef __ASSEMBLY__ -#include -#include -#include - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons, these macros are grossly misnamed. - */ - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) - -#define KERNEL_DS MAKE_MM_SEG(0UL) -#define USER_DS MAKE_MM_SEG(0xf000000000000000UL) - -#define get_ds() (KERNEL_DS) -#define get_fs() (current->thread.fs) -#define set_fs(val) (current->thread.fs = (val)) - -#define segment_eq(a,b) ((a).seg == (b).seg) - -/* - * Use the alpha trick for checking ranges: - * - * Is a address valid? This does a straightforward calculation rather - * than tests. - * - * Address valid if: - * - "addr" doesn't have any high-bits set - * - AND "size" doesn't have any high-bits set - * - OR we are in kernel mode. - * - * We dont have to check for high bits in (addr+size) because the first - * two checks force the maximum result to be below the start of the - * kernel region. - */ -#define __access_ok(addr,size,segment) \ - (((segment).seg & (addr | size )) == 0) - -#define access_ok(type,addr,size) \ - __access_ok(((__force unsigned long)(addr)),(size),get_fs()) - -/* - * The exception table consists of pairs of addresses: the first is the - * address of an instruction that is allowed to fault, and the second is - * the address at which the program should continue. No registers are - * modified, so it is entirely up to the continuation code to figure out - * what to do. - * - * All the routines below use bits of fixup code that are out of line - * with the main instruction path. This means when everything is well, - * we don't even have to jump over them. Further, they do not intrude - * on our cache or tlb entries. - */ - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -/* Returns 0 if exception not found and fixup otherwise. */ -extern unsigned long search_exception_table(unsigned long); - -/* - * These are the main single-value transfer routines. They automatically - * use the right size if we just have the right pointer type. - * - * This gets kind of ugly. We want to return _two_ values in "get_user()" - * and yet we don't want to do any pointers, because that is too much - * of a performance impact. Thus we have a few rather ugly macros here, - * and hide all the ugliness from the user. - * - * The "__xxx" versions of the user access functions are versions that - * do not verify the address space, that must have been done previously - * with a separate "access_ok()" call (this is used when we do multiple - * accesses to the same area of user memory). - * - * As we use the same address space for kernel and user data on the - * PowerPC, we can just do these as direct assignments. (Of course, the - * exception handling means that it's no longer "just"...) - */ -#define get_user(x,ptr) \ - __get_user_check((x),(ptr),sizeof(*(ptr))) -#define put_user(x,ptr) \ - __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) - -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) -#define __put_user(x,ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) - -#define __get_user_unaligned __get_user -#define __put_user_unaligned __put_user - -extern long __put_user_bad(void); - -#define __put_user_nocheck(x,ptr,size) \ -({ \ - long __pu_err; \ - might_sleep(); \ - __chk_user_ptr(ptr); \ - __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - void __user *__pu_addr = (ptr); \ - might_sleep(); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \ - __pu_err; \ -}) - -#define __put_user_size(x,ptr,size,retval,errret) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: __put_user_asm(x,ptr,retval,"stb",errret); break; \ - case 2: __put_user_asm(x,ptr,retval,"sth",errret); break; \ - case 4: __put_user_asm(x,ptr,retval,"stw",errret); break; \ - case 8: __put_user_asm(x,ptr,retval,"std",errret); break; \ - default: __put_user_bad(); \ - } \ -} while (0) - -/* - * We don't tell gcc that we are accessing memory, but this is OK - * because we do not write to any memory gcc knows about, so there - * are no aliasing issues. - */ -#define __put_user_asm(x, addr, err, op, errret) \ - __asm__ __volatile__( \ - "1: "op" %1,0(%2) # put_user\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%3\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .llong 1b,3b\n" \ - ".previous" \ - : "=r"(err) \ - : "r"(x), "b"(addr), "i"(errret), "0"(err)) - - -#define __get_user_nocheck(x,ptr,size) \ -({ \ - long __gu_err; \ - unsigned long __gu_val; \ - might_sleep(); \ - __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_check(x,ptr,size) \ -({ \ - long __gu_err = -EFAULT; \ - unsigned long __gu_val = 0; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - might_sleep(); \ - if (access_ok(VERIFY_READ,__gu_addr,size)) \ - __get_user_size(__gu_val,__gu_addr,(size),__gu_err,-EFAULT);\ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -extern long __get_user_bad(void); - -#define __get_user_size(x,ptr,size,retval,errret) \ -do { \ - retval = 0; \ - __chk_user_ptr(ptr); \ - switch (size) { \ - case 1: __get_user_asm(x,ptr,retval,"lbz",errret); break; \ - case 2: __get_user_asm(x,ptr,retval,"lhz",errret); break; \ - case 4: __get_user_asm(x,ptr,retval,"lwz",errret); break; \ - case 8: __get_user_asm(x,ptr,retval,"ld",errret); break; \ - default: (x) = __get_user_bad(); \ - } \ -} while (0) - -#define __get_user_asm(x, addr, err, op, errret) \ - __asm__ __volatile__( \ - "1: "op" %1,0(%2) # get_user\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,%3\n" \ - " li %1,0\n" \ - " b 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .llong 1b,3b\n" \ - ".previous" \ - : "=r"(err), "=r"(x) \ - : "b"(addr), "i"(errret), "0"(err)) - -/* more complex routines */ - -extern unsigned long __copy_tofrom_user(void __user *to, const void __user *from, - unsigned long size); - -static inline unsigned long -__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) -{ - if (__builtin_constant_p(n)) { - unsigned long ret; - - switch (n) { - case 1: - __get_user_size(*(u8 *)to, from, 1, ret, 1); - return ret; - case 2: - __get_user_size(*(u16 *)to, from, 2, ret, 2); - return ret; - case 4: - __get_user_size(*(u32 *)to, from, 4, ret, 4); - return ret; - case 8: - __get_user_size(*(u64 *)to, from, 8, ret, 8); - return ret; - } - } - return __copy_tofrom_user((__force void __user *) to, from, n); -} - -static inline unsigned long -__copy_from_user(void *to, const void __user *from, unsigned long n) -{ - might_sleep(); - return __copy_from_user_inatomic(to, from, n); -} - -static inline unsigned long -__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) -{ - if (__builtin_constant_p(n)) { - unsigned long ret; - - switch (n) { - case 1: - __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); - return ret; - case 2: - __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); - return ret; - case 4: - __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); - return ret; - case 8: - __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret, 8); - return ret; - } - } - return __copy_tofrom_user(to, (__force const void __user *) from, n); -} - -static inline unsigned long -__copy_to_user(void __user *to, const void *from, unsigned long n) -{ - might_sleep(); - return __copy_to_user_inatomic(to, from, n); -} - -#define __copy_in_user(to, from, size) \ - __copy_tofrom_user((to), (from), (size)) - -extern unsigned long copy_from_user(void *to, const void __user *from, - unsigned long n); -extern unsigned long copy_to_user(void __user *to, const void *from, - unsigned long n); -extern unsigned long copy_in_user(void __user *to, const void __user *from, - unsigned long n); - -extern unsigned long __clear_user(void __user *addr, unsigned long size); - -static inline unsigned long -clear_user(void __user *addr, unsigned long size) -{ - might_sleep(); - if (likely(access_ok(VERIFY_WRITE, addr, size))) - size = __clear_user(addr, size); - return size; -} - -extern int __strncpy_from_user(char *dst, const char __user *src, long count); - -static inline long -strncpy_from_user(char *dst, const char __user *src, long count) -{ - might_sleep(); - if (likely(access_ok(VERIFY_READ, src, 1))) - return __strncpy_from_user(dst, src, count); - return -EFAULT; -} - -/* - * Return the size of a string (including the ending 0) - * - * Return 0 for error - */ -extern int __strnlen_user(const char __user *str, long len); - -/* - * Returns the length of the string at str (including the null byte), - * or 0 if we hit a page we can't access, - * or something > len if we didn't find a null byte. - */ -static inline int strnlen_user(const char __user *str, long len) -{ - might_sleep(); - if (likely(access_ok(VERIFY_READ, str, 1))) - return __strnlen_user(str, len); - return 0; -} - -#define strlen_user(str) strnlen_user((str), 0x7ffffffe) - -#endif /* __ASSEMBLY__ */ - -#endif /* _PPC64_UACCESS_H */ -- cgit v1.2.3 From 5015b49448cbe5352b9cc232333ab26f3e608a07 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 31 Oct 2005 18:39:20 +1100 Subject: powerpc: fix __strnlen_user in merge tree Change USER/KERNEL_DS so that the merged version of __strnlen_user can be used which allows us to complete the removal of arch/ppc64/lib/. Signed-off-by: Stephen Rothwell --- arch/powerpc/lib/Makefile | 2 +- arch/ppc64/Makefile | 1 - arch/ppc64/lib/Makefile | 5 -- arch/ppc64/lib/string.S | 179 ------------------------------------------ include/asm-powerpc/uaccess.h | 113 +++++++++++--------------- 5 files changed, 46 insertions(+), 254 deletions(-) delete mode 100644 arch/ppc64/lib/Makefile delete mode 100644 arch/ppc64/lib/string.S (limited to 'include') diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index e6b2be3bcec1..dfb33915ad61 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -9,7 +9,7 @@ endif obj-y += strcase.o obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ - memcpy_64.o usercopy_64.o mem_64.o + memcpy_64.o usercopy_64.o mem_64.o string.o obj-$(CONFIG_PPC_ISERIES) += e2a.o obj-$(CONFIG_XMON) += sstep.o diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile index fdbd6f44adc0..a55a82d145d4 100644 --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -86,7 +86,6 @@ head-y := arch/ppc64/kernel/head.o head-y += arch/powerpc/kernel/fpu.o head-y += arch/powerpc/kernel/entry_64.o -libs-y += arch/ppc64/lib/ core-y += arch/ppc64/kernel/ arch/powerpc/kernel/ core-y += arch/powerpc/mm/ core-y += arch/powerpc/sysdev/ diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile deleted file mode 100644 index 42d5295bf345..000000000000 --- a/arch/ppc64/lib/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for ppc64-specific library files.. -# - -lib-y := string.o diff --git a/arch/ppc64/lib/string.S b/arch/ppc64/lib/string.S deleted file mode 100644 index e21a0038a4d6..000000000000 --- a/arch/ppc64/lib/string.S +++ /dev/null @@ -1,179 +0,0 @@ -/* - * String handling functions for PowerPC. - * - * Copyright (C) 1996 Paul Mackerras. - * - * 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 - -_GLOBAL(strcpy) - addi r5,r3,-1 - addi r4,r4,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r5) - bne 1b - blr - -_GLOBAL(strncpy) - cmpwi 0,r5,0 - beqlr - mtctr r5 - addi r6,r3,-1 - addi r4,r4,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r6) - bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ - blr - -_GLOBAL(strcat) - addi r5,r3,-1 - addi r4,r4,-1 -1: lbzu r0,1(r5) - cmpwi 0,r0,0 - bne 1b - addi r5,r5,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r5) - bne 1b - blr - -_GLOBAL(strcmp) - addi r5,r3,-1 - addi r4,r4,-1 -1: lbzu r3,1(r5) - cmpwi 1,r3,0 - lbzu r0,1(r4) - subf. r3,r0,r3 - beqlr 1 - beq 1b - blr - -_GLOBAL(strlen) - addi r4,r3,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - bne 1b - subf r3,r3,r4 - blr - -_GLOBAL(memcmp) - cmpwi 0,r5,0 - ble- 2f - mtctr r5 - addi r6,r3,-1 - addi r4,r4,-1 -1: lbzu r3,1(r6) - lbzu r0,1(r4) - subf. r3,r0,r3 - bdnzt 2,1b - blr -2: li r3,0 - blr - -_GLOBAL(memchr) - cmpwi 0,r5,0 - ble- 2f - mtctr r5 - addi r3,r3,-1 -1: lbzu r0,1(r3) - cmpw 0,r0,r4 - bdnzf 2,1b - beqlr -2: li r3,0 - blr - -_GLOBAL(__clear_user) - addi r6,r3,-4 - li r3,0 - li r5,0 - cmplwi 0,r4,4 - blt 7f - /* clear a single word */ -11: stwu r5,4(r6) - beqlr - /* clear word sized chunks */ - andi. r0,r6,3 - add r4,r0,r4 - subf r6,r0,r6 - srwi r0,r4,2 - andi. r4,r4,3 - mtctr r0 - bdz 7f -1: stwu r5,4(r6) - bdnz 1b - /* clear byte sized chunks */ -7: cmpwi 0,r4,0 - beqlr - mtctr r4 - addi r6,r6,3 -8: stbu r5,1(r6) - bdnz 8b - blr -90: mr r3,r4 - blr -91: mfctr r3 - slwi r3,r3,2 - add r3,r3,r4 - blr -92: mfctr r3 - blr - - .section __ex_table,"a" - .align 3 - .llong 11b,90b - .llong 1b,91b - .llong 8b,92b - .text - -/* r3 = dst, r4 = src, r5 = count */ -_GLOBAL(__strncpy_from_user) - addi r6,r3,-1 - addi r4,r4,-1 - cmpwi 0,r5,0 - beq 2f - mtctr r5 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r6) - bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ - beq 3f -2: addi r6,r6,1 -3: subf r3,r3,r6 - blr -99: li r3,-EFAULT - blr - - .section __ex_table,"a" - .align 3 - .llong 1b,99b - .text - -/* r3 = str, r4 = len (> 0) */ -_GLOBAL(__strnlen_user) - addi r7,r3,-1 - mtctr r4 /* ctr = len */ -1: lbzu r0,1(r7) /* get next byte */ - cmpwi 0,r0,0 - bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */ - addi r7,r7,1 - subf r3,r3,r7 /* number of bytes we have looked at */ - beqlr /* return if we found a 0 byte */ - cmpw 0,r3,r4 /* did we look at all len bytes? */ - blt 99f /* if not, must have hit top */ - addi r3,r4,1 /* return len + 1 to indicate no null found */ - blr -99: li r3,0 /* bad address, return 0 */ - blr - - .section __ex_table,"a" - .align 3 - .llong 1b,99b diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index 2ecc3e16e49e..035338b0c5ee 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h @@ -24,11 +24,11 @@ #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) +#define KERNEL_DS MAKE_MM_SEG(~0UL) #ifdef __powerpc64__ -#define KERNEL_DS MAKE_MM_SEG(0UL) -#define USER_DS MAKE_MM_SEG(0xf000000000000000UL) +/* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */ +#define USER_DS MAKE_MM_SEG(TASK_SIZE_USER64 - 1) #else -#define KERNEL_DS MAKE_MM_SEG(~0UL) #define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) #endif @@ -40,22 +40,11 @@ #ifdef __powerpc64__ /* - * Use the alpha trick for checking ranges: - * - * Is a address valid? This does a straightforward calculation rather - * than tests. - * - * Address valid if: - * - "addr" doesn't have any high-bits set - * - AND "size" doesn't have any high-bits set - * - OR we are in kernel mode. - * - * We dont have to check for high bits in (addr+size) because the first - * two checks force the maximum result to be below the start of the - * kernel region. + * This check is sufficient because there is a large enough + * gap between user addresses and the kernel addresses */ #define __access_ok(addr, size, segment) \ - (((segment).seg & (addr | size )) == 0) + (((addr) <= (segment).seg) && ((size) <= (segment).seg)) #else @@ -161,7 +150,10 @@ extern long __put_user_bad(void); : "=r" (err) \ : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) -#ifndef __powerpc64__ +#ifdef __powerpc64__ +#define __put_user_asm2(x, ptr, retval) \ + __put_user_asm(x, ptr, retval, "std") +#else /* __powerpc64__ */ #define __put_user_asm2(x, addr, err) \ __asm__ __volatile__( \ "1: stw %1,0(%2)\n" \ @@ -178,9 +170,6 @@ extern long __put_user_bad(void); ".previous" \ : "=r" (err) \ : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) -#else /* __powerpc64__ */ -#define __put_user_asm2(x, ptr, retval) \ - __put_user_asm(x, ptr, retval, "std") #endif /* __powerpc64__ */ #define __put_user_size(x, ptr, size, retval) \ @@ -218,7 +207,7 @@ extern long __get_user_bad(void); #define __get_user_asm(x, addr, err, op) \ __asm__ __volatile__( \ - "1: "op" %1,0(%2) # get_user\n" \ + "1: "op" %1,0(%2) # get_user\n" \ "2:\n" \ ".section .fixup,\"ax\"\n" \ "3: li %0,%3\n" \ @@ -232,8 +221,11 @@ extern long __get_user_bad(void); : "=r" (err), "=r" (x) \ : "b" (addr), "i" (-EFAULT), "0" (err)) -#ifndef __powerpc64__ -#define __get_user_asm2(x, addr, err) \ +#ifdef __powerpc64__ +#define __get_user_asm2(x, addr, err) \ + __get_user_asm(x, addr, err, "ld") +#else /* __powerpc64__ */ +#define __get_user_asm2(x, addr, err) \ __asm__ __volatile__( \ "1: lwz %1,0(%2)\n" \ "2: lwz %1+1,4(%2)\n" \ @@ -251,17 +243,14 @@ extern long __get_user_bad(void); ".previous" \ : "=r" (err), "=&r" (x) \ : "b" (addr), "i" (-EFAULT), "0" (err)) -#else -#define __get_user_asm2(x, addr, err) \ - __get_user_asm(x, addr, err, "ld") #endif /* __powerpc64__ */ #define __get_user_size(x, ptr, size, retval) \ do { \ retval = 0; \ __chk_user_ptr(ptr); \ - if (size > sizeof(x)) \ - (x) = __get_user_bad(); \ + if (size > sizeof(x)) \ + (x) = __get_user_bad(); \ switch (size) { \ case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \ case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \ @@ -300,7 +289,7 @@ do { \ long __gu_err = -EFAULT; \ unsigned long __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - might_sleep(); \ + might_sleep(); \ if (access_ok(VERIFY_READ, __gu_addr, (size))) \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ (x) = (__typeof__(*(ptr)))__gu_val; \ @@ -313,8 +302,9 @@ extern unsigned long __copy_tofrom_user(void __user *to, const void __user *from, unsigned long size); #ifndef __powerpc64__ -extern inline unsigned long -copy_from_user(void *to, const void __user *from, unsigned long n) + +extern inline unsigned long copy_from_user(void *to, + const void __user *from, unsigned long n) { unsigned long over; @@ -328,8 +318,8 @@ copy_from_user(void *to, const void __user *from, unsigned long n) return n; } -extern inline unsigned long -copy_to_user(void __user *to, const void *from, unsigned long n) +extern inline unsigned long copy_to_user(void __user *to, + const void *from, unsigned long n) { unsigned long over; @@ -343,10 +333,23 @@ copy_to_user(void __user *to, const void *from, unsigned long n) return n; } +#define __copy_to_user_inatomic __copy_to_user +#define __copy_from_user_inatomic __copy_from_user + #else /* __powerpc64__ */ -static inline unsigned long -__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) +#define __copy_in_user(to, from, size) \ + __copy_tofrom_user((to), (from), (size)) + +extern unsigned long copy_from_user(void *to, const void __user *from, + unsigned long n); +extern unsigned long copy_to_user(void __user *to, const void *from, + unsigned long n); +extern unsigned long copy_in_user(void __user *to, const void __user *from, + unsigned long n); + +static inline unsigned long __copy_from_user_inatomic(void *to, + const void __user *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { unsigned long ret; @@ -370,8 +373,8 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) return __copy_tofrom_user((__force void __user *) to, from, n); } -static inline unsigned long -__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) +static inline unsigned long __copy_to_user_inatomic(void __user *to, + const void *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { unsigned long ret; @@ -397,8 +400,8 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) #endif /* __powerpc64__ */ -static inline unsigned long -__copy_from_user(void *to, const void __user *from, unsigned long size) +static inline unsigned long __copy_from_user(void *to, + const void __user *from, unsigned long size) { might_sleep(); #ifndef __powerpc64__ @@ -408,8 +411,8 @@ __copy_from_user(void *to, const void __user *from, unsigned long size) #endif /* __powerpc64__ */ } -static inline unsigned long -__copy_to_user(void __user *to, const void *from, unsigned long size) +static inline unsigned long __copy_to_user(void __user *to, + const void *from, unsigned long size) { might_sleep(); #ifndef __powerpc64__ @@ -419,21 +422,6 @@ __copy_to_user(void __user *to, const void *from, unsigned long size) #endif /* __powerpc64__ */ } -#ifndef __powerpc64__ -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user -#else /* __powerpc64__ */ -#define __copy_in_user(to, from, size) \ - __copy_tofrom_user((to), (from), (size)) - -extern unsigned long copy_from_user(void *to, const void __user *from, - unsigned long n); -extern unsigned long copy_to_user(void __user *to, const void *from, - unsigned long n); -extern unsigned long copy_in_user(void __user *to, const void __user *from, - unsigned long n); -#endif /* __powerpc64__ */ - extern unsigned long __clear_user(void __user *addr, unsigned long size); static inline unsigned long clear_user(void __user *addr, unsigned long size) @@ -466,11 +454,7 @@ static inline long strncpy_from_user(char *dst, const char __user *src, * * Return 0 for error */ -#ifndef __powerpc64__ extern int __strnlen_user(const char __user *str, long len, unsigned long top); -#else /* __powerpc64__ */ -extern int __strnlen_user(const char __user *str, long len); -#endif /* __powerpc64__ */ /* * Returns the length of the string at str (including the null byte), @@ -482,18 +466,11 @@ extern int __strnlen_user(const char __user *str, long len); */ static inline int strnlen_user(const char __user *str, long len) { -#ifndef __powerpc64__ unsigned long top = current->thread.fs.seg; if ((unsigned long)str > top) return 0; return __strnlen_user(str, len, top); -#else /* __powerpc64__ */ - might_sleep(); - if (likely(access_ok(VERIFY_READ, str, 1))) - return __strnlen_user(str, len); - return 0; -#endif /* __powerpc64__ */ } #define strlen_user(str) strnlen_user((str), 0x7ffffffe) -- cgit v1.2.3 From 870c6ff2ac0cb708697c2c06f3e5eddf9e3b38cb Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 1 Nov 2005 14:36:30 +1100 Subject: powerpc: remove duplicate ioctl definitions Signed-off-by: Stephen Rothwell --- include/asm-powerpc/ioctls.h | 3 ++ include/asm-powerpc/termios.h | 101 ------------------------------------------ 2 files changed, 3 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/ioctls.h b/include/asm-powerpc/ioctls.h index 5b94ff489b8b..279a6229584b 100644 --- a/include/asm-powerpc/ioctls.h +++ b/include/asm-powerpc/ioctls.h @@ -62,6 +62,9 @@ # define TIOCM_DSR 0x100 # define TIOCM_CD TIOCM_CAR # define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 #define TIOCGSOFTCAR 0x5419 #define TIOCSSOFTCAR 0x541A diff --git a/include/asm-powerpc/termios.h b/include/asm-powerpc/termios.h index c5b8e5358f83..27a012cfcb4e 100644 --- a/include/asm-powerpc/termios.h +++ b/include/asm-powerpc/termios.h @@ -94,107 +94,6 @@ struct termio { #define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" #endif -#define FIOCLEX _IO('f', 1) -#define FIONCLEX _IO('f', 2) -#define FIOASYNC _IOW('f', 125, int) -#define FIONBIO _IOW('f', 126, int) -#define FIONREAD _IOR('f', 127, int) -#define TIOCINQ FIONREAD - -#define TIOCGETP _IOR('t', 8, struct sgttyb) -#define TIOCSETP _IOW('t', 9, struct sgttyb) -#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ - -#define TIOCSETC _IOW('t', 17, struct tchars) -#define TIOCGETC _IOR('t', 18, struct tchars) -#define TCGETS _IOR('t', 19, struct termios) -#define TCSETS _IOW('t', 20, struct termios) -#define TCSETSW _IOW('t', 21, struct termios) -#define TCSETSF _IOW('t', 22, struct termios) - -#define TCGETA _IOR('t', 23, struct termio) -#define TCSETA _IOW('t', 24, struct termio) -#define TCSETAW _IOW('t', 25, struct termio) -#define TCSETAF _IOW('t', 28, struct termio) - -#define TCSBRK _IO('t', 29) -#define TCXONC _IO('t', 30) -#define TCFLSH _IO('t', 31) - -#define TIOCSWINSZ _IOW('t', 103, struct winsize) -#define TIOCGWINSZ _IOR('t', 104, struct winsize) -#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ -#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ -#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ - -#define TIOCGLTC _IOR('t', 116, struct ltchars) -#define TIOCSLTC _IOW('t', 117, struct ltchars) -#define TIOCSPGRP _IOW('t', 118, int) -#define TIOCGPGRP _IOR('t', 119, int) - -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E - -#define TIOCSTI 0x5412 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 - -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ - -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - #ifdef __KERNEL__ /* -- cgit v1.2.3 From 3c4cf5ee5a9224a800a74b5dfcb435550ed30737 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 1 Nov 2005 14:26:41 +1100 Subject: powerpc: use asm-generic/termios.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/termios.h | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/termios.h b/include/asm-powerpc/termios.h index 27a012cfcb4e..7f80a019b6a0 100644 --- a/include/asm-powerpc/termios.h +++ b/include/asm-powerpc/termios.h @@ -96,39 +96,7 @@ struct termio { #ifdef __KERNEL__ -/* - * Translate a "termio" structure into a "termios". Ugh. - */ -#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ - unsigned short __tmp; \ - get_user(__tmp,&(termio)->x); \ - (termios)->x = (0xffff0000 & (termios)->x) | __tmp; \ -} - -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#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)) +#include #endif /* __KERNEL__ */ -- cgit v1.2.3 From 48fe4871569f019c653efb95b26dda976f84c468 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 1 Nov 2005 15:53:19 +1100 Subject: powerpc: clean up uaccess.h Use the best from each architecture. Signed-off-by: Stephen Rothwell --- include/asm-powerpc/uaccess.h | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index 035338b0c5ee..33af730f0d19 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h @@ -115,10 +115,8 @@ struct exception_table_entry { #define __put_user64(x, ptr) __put_user(x, ptr) #endif -#ifdef __powerpc64__ #define __get_user_unaligned __get_user #define __put_user_unaligned __put_user -#endif extern long __put_user_bad(void); @@ -333,9 +331,6 @@ extern inline unsigned long copy_to_user(void __user *to, return n; } -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - #else /* __powerpc64__ */ #define __copy_in_user(to, from, size) \ @@ -348,6 +343,8 @@ extern unsigned long copy_to_user(void __user *to, const void *from, extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned long n); +#endif /* __powerpc64__ */ + static inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { @@ -368,9 +365,10 @@ static inline unsigned long __copy_from_user_inatomic(void *to, __get_user_size(*(u64 *)to, from, 8, ret); break; } - return (ret == -EFAULT) ? n : 0; + if (ret == 0) + return 0; } - return __copy_tofrom_user((__force void __user *) to, from, n); + return __copy_tofrom_user((__force void __user *)to, from, n); } static inline unsigned long __copy_to_user_inatomic(void __user *to, @@ -393,33 +391,24 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to, __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret); break; } - return (ret == -EFAULT) ? n : 0; + if (ret == 0) + return 0; } - return __copy_tofrom_user(to, (__force const void __user *) from, n); + return __copy_tofrom_user(to, (__force const void __user *)from, n); } -#endif /* __powerpc64__ */ - static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long size) { might_sleep(); -#ifndef __powerpc64__ - return __copy_tofrom_user((__force void __user *)to, from, size); -#else /* __powerpc64__ */ return __copy_from_user_inatomic(to, from, size); -#endif /* __powerpc64__ */ } static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long size) { might_sleep(); -#ifndef __powerpc64__ - return __copy_tofrom_user(to, (__force void __user *)from, size); -#else /* __powerpc64__ */ return __copy_to_user_inatomic(to, from, size); -#endif /* __powerpc64__ */ } extern unsigned long __clear_user(void __user *addr, unsigned long size); @@ -429,12 +418,10 @@ static inline unsigned long clear_user(void __user *addr, unsigned long size) might_sleep(); if (likely(access_ok(VERIFY_WRITE, addr, size))) return __clear_user(addr, size); -#ifndef __powerpc64__ if ((unsigned long)addr < TASK_SIZE) { unsigned long over = (unsigned long)addr + size - TASK_SIZE; return __clear_user(addr, size - over) + over; } -#endif /* __powerpc64__ */ return size; } -- cgit v1.2.3 From 1da44037883c0405154d53fe76da27e078456664 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Tue, 1 Nov 2005 16:59:20 +1100 Subject: merge filename and modify references to iseries/hv_call.h Signed-off-by: Kelly Daly --- arch/powerpc/lib/locks.c | 2 +- arch/powerpc/platforms/iseries/hvlog.c | 2 +- arch/powerpc/platforms/iseries/smp.c | 2 +- drivers/char/viocons.c | 2 +- include/asm-powerpc/iseries/hv_call.h | 113 +++++++++++++++++++++++++++++++++ include/asm-powerpc/time.h | 2 +- include/asm-ppc64/iSeries/HvCall.h | 113 --------------------------------- include/asm-ppc64/spinlock.h | 2 +- 8 files changed, 119 insertions(+), 119 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_call.h delete mode 100644 include/asm-ppc64/iSeries/HvCall.h (limited to 'include') diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 3794715b2972..2a912f411eb4 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -22,7 +22,7 @@ /* waiting for a spinlock... */ #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) #include -#include +#include void __spin_yield(raw_spinlock_t *lock) { diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c index f61e2e9ac9ec..5a89b481f978 100644 --- a/arch/powerpc/platforms/iseries/hvlog.c +++ b/arch/powerpc/platforms/iseries/hvlog.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index f720916682f6..3336bad67724 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 44f5fb4a46ef..180507ae590f 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -49,7 +49,7 @@ #include #include #include -#include +#include #ifdef CONFIG_VT #error You must turn off CONFIG_VT to use CONFIG_VIOCONS diff --git a/include/asm-powerpc/iseries/hv_call.h b/include/asm-powerpc/iseries/hv_call.h new file mode 100644 index 000000000000..c3f19475c0d9 --- /dev/null +++ b/include/asm-powerpc/iseries/hv_call.h @@ -0,0 +1,113 @@ +/* + * HvCall.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * This file contains the "hypervisor call" interface which is used to + * drive the hypervisor from the OS. + */ +#ifndef _HVCALL_H +#define _HVCALL_H + +#include +#include +#include + +/* Type of yield for HvCallBaseYieldProcessor */ +#define HvCall_YieldTimed 0 /* Yield until specified time (tb) */ +#define HvCall_YieldToActive 1 /* Yield until all active procs have run */ +#define HvCall_YieldToProc 2 /* Yield until the specified processor has run */ + +/* interrupt masks for setEnabledInterrupts */ +#define HvCall_MaskIPI 0x00000001 +#define HvCall_MaskLpEvent 0x00000002 +#define HvCall_MaskLpProd 0x00000004 +#define HvCall_MaskTimeout 0x00000008 + +/* Log buffer formats */ +#define HvCall_LogBuffer_ASCII 0 +#define HvCall_LogBuffer_EBCDIC 1 + +#define HvCallBaseAckDeferredInts HvCallBase + 0 +#define HvCallBaseCpmPowerOff HvCallBase + 1 +#define HvCallBaseGetHwPatch HvCallBase + 2 +#define HvCallBaseReIplSpAttn HvCallBase + 3 +#define HvCallBaseSetASR HvCallBase + 4 +#define HvCallBaseSetASRAndRfi HvCallBase + 5 +#define HvCallBaseSetIMR HvCallBase + 6 +#define HvCallBaseSendIPI HvCallBase + 7 +#define HvCallBaseTerminateMachine HvCallBase + 8 +#define HvCallBaseTerminateMachineSrc HvCallBase + 9 +#define HvCallBaseProcessPlicInterrupts HvCallBase + 10 +#define HvCallBaseIsPrimaryCpmOrMsdIpl HvCallBase + 11 +#define HvCallBaseSetVirtualSIT HvCallBase + 12 +#define HvCallBaseVaryOffThisProcessor HvCallBase + 13 +#define HvCallBaseVaryOffMemoryChunk HvCallBase + 14 +#define HvCallBaseVaryOffInteractivePercentage HvCallBase + 15 +#define HvCallBaseSendLpProd HvCallBase + 16 +#define HvCallBaseSetEnabledInterrupts HvCallBase + 17 +#define HvCallBaseYieldProcessor HvCallBase + 18 +#define HvCallBaseVaryOffSharedProcUnits HvCallBase + 19 +#define HvCallBaseSetVirtualDecr HvCallBase + 20 +#define HvCallBaseClearLogBuffer HvCallBase + 21 +#define HvCallBaseGetLogBufferCodePage HvCallBase + 22 +#define HvCallBaseGetLogBufferFormat HvCallBase + 23 +#define HvCallBaseGetLogBufferLength HvCallBase + 24 +#define HvCallBaseReadLogBuffer HvCallBase + 25 +#define HvCallBaseSetLogBufferFormatAndCodePage HvCallBase + 26 +#define HvCallBaseWriteLogBuffer HvCallBase + 27 +#define HvCallBaseRouter28 HvCallBase + 28 +#define HvCallBaseRouter29 HvCallBase + 29 +#define HvCallBaseRouter30 HvCallBase + 30 +#define HvCallBaseSetDebugBus HvCallBase + 31 + +#define HvCallCcSetDABR HvCallCc + 7 + +static inline void HvCall_setVirtualDecr(void) +{ + /* + * Ignore any error return codes - most likely means that the + * target value for the LP has been increased and this vary off + * would bring us below the new target. + */ + HvCall0(HvCallBaseSetVirtualDecr); +} + +static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm) +{ + HvCall2(HvCallBaseYieldProcessor, typeOfYield, yieldParm); +} + +static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts) +{ + HvCall1(HvCallBaseSetEnabledInterrupts, enabledInterrupts); +} + +static inline void HvCall_setLogBufferFormatAndCodepage(int format, + u32 codePage) +{ + HvCall2(HvCallBaseSetLogBufferFormatAndCodePage, format, codePage); +} + +extern void HvCall_writeLogBuffer(const void *buffer, u64 bufLen); + +static inline void HvCall_sendIPI(struct paca_struct *targetPaca) +{ + HvCall1(HvCallBaseSendIPI, targetPaca->paca_index); +} + +#endif /* _HVCALL_H */ diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index 410e795f7d43..d9b86a17271b 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -21,7 +21,7 @@ #include #ifdef CONFIG_PPC64 #include -#include +#include #endif /* time.c */ diff --git a/include/asm-ppc64/iSeries/HvCall.h b/include/asm-ppc64/iSeries/HvCall.h deleted file mode 100644 index c3f19475c0d9..000000000000 --- a/include/asm-ppc64/iSeries/HvCall.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * HvCall.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * This file contains the "hypervisor call" interface which is used to - * drive the hypervisor from the OS. - */ -#ifndef _HVCALL_H -#define _HVCALL_H - -#include -#include -#include - -/* Type of yield for HvCallBaseYieldProcessor */ -#define HvCall_YieldTimed 0 /* Yield until specified time (tb) */ -#define HvCall_YieldToActive 1 /* Yield until all active procs have run */ -#define HvCall_YieldToProc 2 /* Yield until the specified processor has run */ - -/* interrupt masks for setEnabledInterrupts */ -#define HvCall_MaskIPI 0x00000001 -#define HvCall_MaskLpEvent 0x00000002 -#define HvCall_MaskLpProd 0x00000004 -#define HvCall_MaskTimeout 0x00000008 - -/* Log buffer formats */ -#define HvCall_LogBuffer_ASCII 0 -#define HvCall_LogBuffer_EBCDIC 1 - -#define HvCallBaseAckDeferredInts HvCallBase + 0 -#define HvCallBaseCpmPowerOff HvCallBase + 1 -#define HvCallBaseGetHwPatch HvCallBase + 2 -#define HvCallBaseReIplSpAttn HvCallBase + 3 -#define HvCallBaseSetASR HvCallBase + 4 -#define HvCallBaseSetASRAndRfi HvCallBase + 5 -#define HvCallBaseSetIMR HvCallBase + 6 -#define HvCallBaseSendIPI HvCallBase + 7 -#define HvCallBaseTerminateMachine HvCallBase + 8 -#define HvCallBaseTerminateMachineSrc HvCallBase + 9 -#define HvCallBaseProcessPlicInterrupts HvCallBase + 10 -#define HvCallBaseIsPrimaryCpmOrMsdIpl HvCallBase + 11 -#define HvCallBaseSetVirtualSIT HvCallBase + 12 -#define HvCallBaseVaryOffThisProcessor HvCallBase + 13 -#define HvCallBaseVaryOffMemoryChunk HvCallBase + 14 -#define HvCallBaseVaryOffInteractivePercentage HvCallBase + 15 -#define HvCallBaseSendLpProd HvCallBase + 16 -#define HvCallBaseSetEnabledInterrupts HvCallBase + 17 -#define HvCallBaseYieldProcessor HvCallBase + 18 -#define HvCallBaseVaryOffSharedProcUnits HvCallBase + 19 -#define HvCallBaseSetVirtualDecr HvCallBase + 20 -#define HvCallBaseClearLogBuffer HvCallBase + 21 -#define HvCallBaseGetLogBufferCodePage HvCallBase + 22 -#define HvCallBaseGetLogBufferFormat HvCallBase + 23 -#define HvCallBaseGetLogBufferLength HvCallBase + 24 -#define HvCallBaseReadLogBuffer HvCallBase + 25 -#define HvCallBaseSetLogBufferFormatAndCodePage HvCallBase + 26 -#define HvCallBaseWriteLogBuffer HvCallBase + 27 -#define HvCallBaseRouter28 HvCallBase + 28 -#define HvCallBaseRouter29 HvCallBase + 29 -#define HvCallBaseRouter30 HvCallBase + 30 -#define HvCallBaseSetDebugBus HvCallBase + 31 - -#define HvCallCcSetDABR HvCallCc + 7 - -static inline void HvCall_setVirtualDecr(void) -{ - /* - * Ignore any error return codes - most likely means that the - * target value for the LP has been increased and this vary off - * would bring us below the new target. - */ - HvCall0(HvCallBaseSetVirtualDecr); -} - -static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm) -{ - HvCall2(HvCallBaseYieldProcessor, typeOfYield, yieldParm); -} - -static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts) -{ - HvCall1(HvCallBaseSetEnabledInterrupts, enabledInterrupts); -} - -static inline void HvCall_setLogBufferFormatAndCodepage(int format, - u32 codePage) -{ - HvCall2(HvCallBaseSetLogBufferFormatAndCodePage, format, codePage); -} - -extern void HvCall_writeLogBuffer(const void *buffer, u64 bufLen); - -static inline void HvCall_sendIPI(struct paca_struct *targetPaca) -{ - HvCall1(HvCallBaseSendIPI, targetPaca->paca_index); -} - -#endif /* _HVCALL_H */ diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h index 14cb895bb607..7d84fb5e39f1 100644 --- a/include/asm-ppc64/spinlock.h +++ b/include/asm-ppc64/spinlock.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #define __raw_spin_is_locked(x) ((x)->slock != 0) -- cgit v1.2.3 From f3f66f599db131ea57dc567ffd931d269dbc690e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 Oct 2005 20:08:37 -0500 Subject: [PATCH] powerpc: Rename BPA to Cell The official name for BPA is now CBEA (Cell Broadband Engine Architecture). This patch renames all occurences of the term BPA to 'Cell' for easier recognition. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 8 +++--- arch/powerpc/kernel/prom_init.c | 2 +- arch/powerpc/kernel/setup_64.c | 6 ++--- arch/powerpc/kernel/traps.c | 4 +-- arch/ppc64/kernel/Makefile | 2 +- arch/ppc64/kernel/bpa_iic.c | 8 +++--- arch/ppc64/kernel/bpa_iic.h | 8 +++--- arch/ppc64/kernel/bpa_iommu.c | 44 +++++++++++++++--------------- arch/ppc64/kernel/bpa_iommu.h | 10 +++---- arch/ppc64/kernel/bpa_nvram.c | 60 ++++++++++++++++++++--------------------- arch/ppc64/kernel/bpa_setup.c | 46 +++++++++++++++---------------- arch/ppc64/kernel/irq.c | 2 +- arch/ppc64/kernel/proc_ppc64.c | 2 +- arch/ppc64/kernel/prom_init.c | 4 +-- arch/ppc64/kernel/spider-pic.c | 2 +- include/asm-powerpc/irq.h | 2 +- include/asm-powerpc/processor.h | 2 +- include/asm-ppc64/nvram.h | 2 +- 18 files changed, 107 insertions(+), 107 deletions(-) (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 967ecf92d6a7..0bd315de156b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -319,8 +319,8 @@ config PPC_MAPLE This option enables support for the Maple 970FX Evaluation Board. For more informations, refer to -config PPC_BPA - bool " Broadband Processor Architecture" +config PPC_CELL + bool " Cell Broadband Processor Architecture" depends on PPC_MULTIPLATFORM && PPC64 select PPC_RTAS @@ -358,8 +358,8 @@ config MPIC_BROKEN_U3 depends on PPC_MAPLE default y -config BPA_IIC - depends on PPC_BPA +config CELL_IIC + depends on PPC_CELL bool default y diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 9750b3cd8ecd..c758b6624d7b 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2000,7 +2000,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, #endif /* - * On pSeries and BPA, copy the CPU hold code + * Copy the CPU hold code */ if (RELOC(of_platform) != PLATFORM_POWERMAC) copy_and_flush(0, KERNELBASE + offset, 0x100, 0); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 19530ce9cd27..70ead7d0d12e 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -296,7 +296,7 @@ static void __init setup_cpu_maps(void) extern struct machdep_calls pSeries_md; extern struct machdep_calls pmac_md; extern struct machdep_calls maple_md; -extern struct machdep_calls bpa_md; +extern struct machdep_calls cell_md; extern struct machdep_calls iseries_md; /* Ultimately, stuff them in an elf section like initcalls... */ @@ -310,8 +310,8 @@ static struct machdep_calls __initdata *machines[] = { #ifdef CONFIG_PPC_MAPLE &maple_md, #endif /* CONFIG_PPC_MAPLE */ -#ifdef CONFIG_PPC_BPA - &bpa_md, +#ifdef CONFIG_PPC_CELL + &cell_md, #endif #ifdef CONFIG_PPC_ISERIES &iseries_md, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 5d638ecddbd0..bb0d00284a7e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -147,8 +147,8 @@ int die(const char *str, struct pt_regs *regs, long err) printk("POWERMAC "); nl = 1; break; - case PLATFORM_BPA: - printk("BPA "); + case PLATFORM_CELL: + printk("CELL "); nl = 1; break; } diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 327c08ce4291..a01a9de9eb56 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -31,7 +31,7 @@ endif obj-$(CONFIG_PPC_PSERIES) += rtasd.o udbg_16550.o -obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \ +obj-$(CONFIG_PPC_CELL) += bpa_setup.o bpa_iommu.o bpa_nvram.o \ bpa_iic.o spider-pic.o obj-$(CONFIG_KEXEC) += machine_kexec.o diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c index 0aaa878e19d3..7fbe78a9327d 100644 --- a/arch/ppc64/kernel/bpa_iic.c +++ b/arch/ppc64/kernel/bpa_iic.c @@ -1,5 +1,5 @@ /* - * BPA Internal Interrupt Controller + * Cell Internal Interrupt Controller * * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 * @@ -31,7 +31,7 @@ #include #include -#include "bpa_iic.h" +#include "interrupt.h" struct iic_pending_bits { u32 data; @@ -89,7 +89,7 @@ static void iic_end(unsigned int irq) } static struct hw_interrupt_type iic_pic = { - .typename = " BPA-IIC ", + .typename = " CELL-IIC ", .startup = iic_startup, .enable = iic_enable, .disable = iic_disable, @@ -106,7 +106,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending) irq = -1; /* - * This mapping is specific to the Broadband + * This mapping is specific to the Cell Broadband * Engine. We might need to get the numbers * from the device tree to support future CPUs. */ diff --git a/arch/ppc64/kernel/bpa_iic.h b/arch/ppc64/kernel/bpa_iic.h index 6833c3022166..37d58e6fd0c6 100644 --- a/arch/ppc64/kernel/bpa_iic.h +++ b/arch/ppc64/kernel/bpa_iic.h @@ -1,5 +1,5 @@ -#ifndef ASM_BPA_IIC_H -#define ASM_BPA_IIC_H +#ifndef ASM_CELL_PIC_H +#define ASM_CELL_PIC_H #ifdef __KERNEL__ /* * Mapping of IIC pending bits into per-node @@ -21,7 +21,7 @@ * + node number * * don't care * - * A node consists of a Broadband Engine and an optional + * A node consists of a Cell Broadband Engine and an optional * south bridge device providing a maximum of 64 IRQs. * The south bridge may be connected to either IOIF0 * or IOIF1. @@ -59,4 +59,4 @@ extern void spider_init_IRQ(void); extern int spider_get_irq(unsigned long int_pending); #endif -#endif /* ASM_BPA_IIC_H */ +#endif /* ASM_CELL_PIC_H */ diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c index da1b4b7a3269..74f999b4ac9e 100644 --- a/arch/ppc64/kernel/bpa_iommu.c +++ b/arch/ppc64/kernel/bpa_iommu.c @@ -1,5 +1,5 @@ /* - * IOMMU implementation for Broadband Processor Architecture + * IOMMU implementation for Cell Broadband Processor Architecture * We just establish a linear mapping at boot by setting all the * IOPT cache entries in the CPU. * The mapping functions should be identical to pci_direct_iommu, @@ -41,7 +41,7 @@ #include #include -#include "bpa_iommu.h" +#include "iommu.h" static inline unsigned long get_iopt_entry(unsigned long real_address, unsigned long ioid, @@ -276,7 +276,7 @@ static void iommu_dev_setup_null(struct pci_dev *d) { } * for each DMA window used by any device. For now, we * happen to know that there is only one DMA window in use, * starting at iopt_phys_offset. */ -static void bpa_map_iommu(void) +static void cell_map_iommu(void) { unsigned long address; void __iomem *base; @@ -309,7 +309,7 @@ static void bpa_map_iommu(void) } -static void *bpa_alloc_coherent(struct device *hwdev, size_t size, +static void *cell_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { void *ret; @@ -317,65 +317,65 @@ static void *bpa_alloc_coherent(struct device *hwdev, size_t size, ret = (void *)__get_free_pages(flag, get_order(size)); if (ret != NULL) { memset(ret, 0, size); - *dma_handle = virt_to_abs(ret) | BPA_DMA_VALID; + *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID; } return ret; } -static void bpa_free_coherent(struct device *hwdev, size_t size, +static void cell_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long)vaddr, get_order(size)); } -static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr, +static dma_addr_t cell_map_single(struct device *hwdev, void *ptr, size_t size, enum dma_data_direction direction) { - return virt_to_abs(ptr) | BPA_DMA_VALID; + return virt_to_abs(ptr) | CELL_DMA_VALID; } -static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr, +static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction) { } -static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg, +static int cell_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { int i; for (i = 0; i < nents; i++, sg++) { sg->dma_address = (page_to_phys(sg->page) + sg->offset) - | BPA_DMA_VALID; + | CELL_DMA_VALID; sg->dma_length = sg->length; } return nents; } -static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg, +static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { } -static int bpa_dma_supported(struct device *dev, u64 mask) +static int cell_dma_supported(struct device *dev, u64 mask) { return mask < 0x100000000ull; } -void bpa_init_iommu(void) +void cell_init_iommu(void) { - bpa_map_iommu(); + cell_map_iommu(); /* Direct I/O, IOMMU off */ ppc_md.iommu_dev_setup = iommu_dev_setup_null; ppc_md.iommu_bus_setup = iommu_bus_setup_null; - pci_dma_ops.alloc_coherent = bpa_alloc_coherent; - pci_dma_ops.free_coherent = bpa_free_coherent; - pci_dma_ops.map_single = bpa_map_single; - pci_dma_ops.unmap_single = bpa_unmap_single; - pci_dma_ops.map_sg = bpa_map_sg; - pci_dma_ops.unmap_sg = bpa_unmap_sg; - pci_dma_ops.dma_supported = bpa_dma_supported; + pci_dma_ops.alloc_coherent = cell_alloc_coherent; + pci_dma_ops.free_coherent = cell_free_coherent; + pci_dma_ops.map_single = cell_map_single; + pci_dma_ops.unmap_single = cell_unmap_single; + pci_dma_ops.map_sg = cell_map_sg; + pci_dma_ops.unmap_sg = cell_unmap_sg; + pci_dma_ops.dma_supported = cell_dma_supported; } diff --git a/arch/ppc64/kernel/bpa_iommu.h b/arch/ppc64/kernel/bpa_iommu.h index e547d77dfa04..490d77abfe85 100644 --- a/arch/ppc64/kernel/bpa_iommu.h +++ b/arch/ppc64/kernel/bpa_iommu.h @@ -1,5 +1,5 @@ -#ifndef BPA_IOMMU_H -#define BPA_IOMMU_H +#ifndef CELL_IOMMU_H +#define CELL_IOMMU_H /* some constants */ enum { @@ -55,11 +55,11 @@ enum { /* The high bit needs to be set on every DMA address, only 2GB are addressable */ - BPA_DMA_VALID = 0x80000000, - BPA_DMA_MASK = 0x7fffffff, + CELL_DMA_VALID = 0x80000000, + CELL_DMA_MASK = 0x7fffffff, }; -void bpa_init_iommu(void); +void cell_init_iommu(void); #endif diff --git a/arch/ppc64/kernel/bpa_nvram.c b/arch/ppc64/kernel/bpa_nvram.c index 06a119cfceb5..74e0d31a3559 100644 --- a/arch/ppc64/kernel/bpa_nvram.c +++ b/arch/ppc64/kernel/bpa_nvram.c @@ -1,5 +1,5 @@ /* - * NVRAM for CPBW + * memory mapped NVRAM * * (C) Copyright IBM Corp. 2005 * @@ -30,54 +30,54 @@ #include #include -static void __iomem *bpa_nvram_start; -static long bpa_nvram_len; -static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED; +static void __iomem *mmio_nvram_start; +static long mmio_nvram_len; +static spinlock_t mmio_nvram_lock = SPIN_LOCK_UNLOCKED; -static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index) +static ssize_t mmio_nvram_read(char *buf, size_t count, loff_t *index) { unsigned long flags; - if (*index >= bpa_nvram_len) + if (*index >= mmio_nvram_len) return 0; - if (*index + count > bpa_nvram_len) - count = bpa_nvram_len - *index; + if (*index + count > mmio_nvram_len) + count = mmio_nvram_len - *index; - spin_lock_irqsave(&bpa_nvram_lock, flags); + spin_lock_irqsave(&mmio_nvram_lock, flags); - memcpy_fromio(buf, bpa_nvram_start + *index, count); + memcpy_fromio(buf, mmio_nvram_start + *index, count); - spin_unlock_irqrestore(&bpa_nvram_lock, flags); + spin_unlock_irqrestore(&mmio_nvram_lock, flags); *index += count; return count; } -static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index) +static ssize_t mmio_nvram_write(char *buf, size_t count, loff_t *index) { unsigned long flags; - if (*index >= bpa_nvram_len) + if (*index >= mmio_nvram_len) return 0; - if (*index + count > bpa_nvram_len) - count = bpa_nvram_len - *index; + if (*index + count > mmio_nvram_len) + count = mmio_nvram_len - *index; - spin_lock_irqsave(&bpa_nvram_lock, flags); + spin_lock_irqsave(&mmio_nvram_lock, flags); - memcpy_toio(bpa_nvram_start + *index, buf, count); + memcpy_toio(mmio_nvram_start + *index, buf, count); - spin_unlock_irqrestore(&bpa_nvram_lock, flags); + spin_unlock_irqrestore(&mmio_nvram_lock, flags); *index += count; return count; } -static ssize_t bpa_nvram_get_size(void) +static ssize_t mmio_nvram_get_size(void) { - return bpa_nvram_len; + return mmio_nvram_len; } -int __init bpa_nvram_init(void) +int __init mmio_nvram_init(void) { struct device_node *nvram_node; unsigned long *buffer; @@ -97,20 +97,20 @@ int __init bpa_nvram_init(void) ret = -ENODEV; nvram_addr = buffer[0]; - bpa_nvram_len = buffer[1]; - if ( (!bpa_nvram_len) || (!nvram_addr) ) + mmio_nvram_len = buffer[1]; + if ( (!mmio_nvram_len) || (!nvram_addr) ) goto out; - bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len); - if (!bpa_nvram_start) + mmio_nvram_start = ioremap(nvram_addr, mmio_nvram_len); + if (!mmio_nvram_start) goto out; - printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n", - bpa_nvram_len >> 10, bpa_nvram_start); + printk(KERN_INFO "mmio NVRAM, %luk mapped to %p\n", + mmio_nvram_len >> 10, mmio_nvram_start); - ppc_md.nvram_read = bpa_nvram_read; - ppc_md.nvram_write = bpa_nvram_write; - ppc_md.nvram_size = bpa_nvram_get_size; + ppc_md.nvram_read = mmio_nvram_read; + ppc_md.nvram_write = mmio_nvram_write; + ppc_md.nvram_size = mmio_nvram_get_size; out: of_node_put(nvram_node); diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c index c2dc8f282eb8..9a495634d0c2 100644 --- a/arch/ppc64/kernel/bpa_setup.c +++ b/arch/ppc64/kernel/bpa_setup.c @@ -1,11 +1,11 @@ /* - * linux/arch/ppc/kernel/bpa_setup.c + * linux/arch/powerpc/platforms/cell/cell_setup.c * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) * Modified by PPC64 Team, IBM Corp - * Modified by BPA Team, IBM Deutschland Entwicklung GmbH + * Modified by Cell Team, IBM Deutschland Entwicklung GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,8 +46,8 @@ #include #include -#include "bpa_iic.h" -#include "bpa_iommu.h" +#include "interrupt.h" +#include "iommu.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -55,7 +55,7 @@ #define DBG(fmt...) #endif -void bpa_show_cpuinfo(struct seq_file *m) +void cell_show_cpuinfo(struct seq_file *m) { struct device_node *root; const char *model = ""; @@ -63,22 +63,22 @@ void bpa_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) model = get_property(root, "model", NULL); - seq_printf(m, "machine\t\t: BPA %s\n", model); + seq_printf(m, "machine\t\t: CHRP %s\n", model); of_node_put(root); } -static void bpa_progress(char *s, unsigned short hex) +static void cell_progress(char *s, unsigned short hex) { printk("*** %04x : %s\n", hex, s ? s : ""); } -static void __init bpa_setup_arch(void) +static void __init cell_setup_arch(void) { ppc_md.init_IRQ = iic_init_IRQ; ppc_md.get_irq = iic_get_irq; #ifdef CONFIG_SMP - smp_init_pSeries(); + smp_init_cell(); #endif /* init to some ~sane value until calibrate_delay() runs */ @@ -97,39 +97,39 @@ static void __init bpa_setup_arch(void) conswitchp = &dummy_con; #endif - bpa_nvram_init(); + mmio_nvram_init(); } /* * Early initialization. Relocation is on but do not reference unbolted pages */ -static void __init bpa_init_early(void) +static void __init cell_init_early(void) { - DBG(" -> bpa_init_early()\n"); + DBG(" -> cell_init_early()\n"); hpte_init_native(); - bpa_init_iommu(); + cell_init_iommu(); - ppc64_interrupt_controller = IC_BPA_IIC; + ppc64_interrupt_controller = IC_CELL_PIC; - DBG(" <- bpa_init_early()\n"); + DBG(" <- cell_init_early()\n"); } -static int __init bpa_probe(int platform) +static int __init cell_probe(int platform) { - if (platform != PLATFORM_BPA) + if (platform != PLATFORM_CELL) return 0; return 1; } -struct machdep_calls __initdata bpa_md = { - .probe = bpa_probe, - .setup_arch = bpa_setup_arch, - .init_early = bpa_init_early, - .show_cpuinfo = bpa_show_cpuinfo, +struct machdep_calls __initdata cell_md = { + .probe = cell_probe, + .setup_arch = cell_setup_arch, + .init_early = cell_init_early, + .show_cpuinfo = cell_show_cpuinfo, .restart = rtas_restart, .power_off = rtas_power_off, .halt = rtas_halt, @@ -137,5 +137,5 @@ struct machdep_calls __initdata bpa_md = { .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .progress = bpa_progress, + .progress = cell_progress, }; diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index f41afe545045..b072ed6f77ad 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -392,7 +392,7 @@ int virt_irq_create_mapping(unsigned int real_irq) if (ppc64_interrupt_controller == IC_OPEN_PIC) return real_irq; /* no mapping for openpic (for now) */ - if (ppc64_interrupt_controller == IC_BPA_IIC) + if (ppc64_interrupt_controller == IC_CELL_PIC) return real_irq; /* no mapping for iic either */ /* don't map interrupts < MIN_VIRT_IRQ */ diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c index a87c66a9652a..24e955ee9487 100644 --- a/arch/ppc64/kernel/proc_ppc64.c +++ b/arch/ppc64/kernel/proc_ppc64.c @@ -53,7 +53,7 @@ static int __init proc_ppc64_create(void) if (!root) return 1; - if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_BPA))) + if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_CELL))) return 0; if (!proc_mkdir("rtas", root)) diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 69924ba4d7d9..a4bbca6dbb8b 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1939,9 +1939,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long prom_send_capabilities(); /* - * On pSeries and BPA, copy the CPU hold code + * On pSeries and Cell, copy the CPU hold code */ - if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA)) + if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_CELL)) copy_and_flush(0, KERNELBASE - offset, 0x100, 0); /* diff --git a/arch/ppc64/kernel/spider-pic.c b/arch/ppc64/kernel/spider-pic.c index d5c9a02fb119..e74132188bdf 100644 --- a/arch/ppc64/kernel/spider-pic.c +++ b/arch/ppc64/kernel/spider-pic.c @@ -27,7 +27,7 @@ #include #include -#include "bpa_iic.h" +#include "interrupt.h" /* register layout taken from Spider spec, table 7.4-4 */ enum { diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index c7c3f912a3c2..b3935ea28fff 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -73,7 +73,7 @@ extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); #define IC_INVALID 0 #define IC_OPEN_PIC 1 #define IC_PPC_XIC 2 -#define IC_BPA_IIC 3 +#define IC_CELL_PIC 3 #define IC_ISERIES 4 extern u64 ppc64_interrupt_controller; diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index eee954a001fd..1dc4bf7b52b3 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -70,7 +70,7 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin; #define PLATFORM_LPAR 0x0001 #define PLATFORM_POWERMAC 0x0400 #define PLATFORM_MAPLE 0x0500 -#define PLATFORM_BPA 0x1000 +#define PLATFORM_CELL 0x1000 /* Compatibility with drivers coming from PPC32 world */ #define _machine (systemcfg->platform) diff --git a/include/asm-ppc64/nvram.h b/include/asm-ppc64/nvram.h index dfaa21566c9a..def47d720d3d 100644 --- a/include/asm-ppc64/nvram.h +++ b/include/asm-ppc64/nvram.h @@ -70,7 +70,7 @@ extern struct nvram_partition *nvram_find_partition(int sig, const char *name); extern int pSeries_nvram_init(void); extern int pmac_nvram_init(void); -extern int bpa_nvram_init(void); +extern int mmio_nvram_init(void); /* PowerMac specific nvram stuffs */ -- cgit v1.2.3 From 19fe04755aca56e7d143f7f95b41008138619c5c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 Oct 2005 20:08:38 -0500 Subject: [PATCH] powerpc: create a new arch/powerpc/platforms/cell/smp.c During the conversion to the merge tree, the Cell specific SMP initialization was removed from the pSeries code. This creates a new Cell specific SMP implementation file. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/Makefile | 1 + arch/powerpc/platforms/cell/Makefile | 1 + arch/powerpc/platforms/cell/smp.c | 230 +++++++++++++++++++++++++++++++++++ include/asm-ppc64/smp.h | 1 + 4 files changed, 233 insertions(+) create mode 100644 arch/powerpc/platforms/cell/Makefile create mode 100644 arch/powerpc/platforms/cell/smp.c (limited to 'include') diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 172c0db63504..8836b3a00668 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_85xx) += 85xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ +obj-$(CONFIG_PPC_CELL) += cell/ diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile new file mode 100644 index 000000000000..7710d2e08037 --- /dev/null +++ b/arch/powerpc/platforms/cell/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SMP) += smp.o diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c new file mode 100644 index 000000000000..de96eadf419d --- /dev/null +++ b/arch/powerpc/platforms/cell/smp.c @@ -0,0 +1,230 @@ +/* + * SMP support for BPA machines. + * + * Dave Engebretsen, Peter Bergner, and + * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com + * + * Plus various changes from other IBM teams... + * + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interrupt.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +/* + * The primary thread of each non-boot processor is recorded here before + * smp init. + */ +static cpumask_t of_spin_map; + +extern void pSeries_secondary_smp_init(unsigned long); + +/** + * smp_startup_cpu() - start the given cpu + * + * At boot time, there is nothing to do for primary threads which were + * started from Open Firmware. For anything else, call RTAS with the + * appropriate start location. + * + * Returns: + * 0 - failure + * 1 - success + */ +static inline int __devinit smp_startup_cpu(unsigned int lcpu) +{ + int status; + unsigned long start_here = __pa((u32)*((unsigned long *) + pSeries_secondary_smp_init)); + unsigned int pcpu; + int start_cpu; + + if (cpu_isset(lcpu, of_spin_map)) + /* Already started by OF and sitting in spin loop */ + return 1; + + pcpu = get_hard_smp_processor_id(lcpu); + + /* Fixup atomic count: it exited inside IRQ handler. */ + paca[lcpu].__current->thread_info->preempt_count = 0; + + /* + * If the RTAS start-cpu token does not exist then presume the + * cpu is already spinning. + */ + start_cpu = rtas_token("start-cpu"); + if (start_cpu == RTAS_UNKNOWN_SERVICE) + return 1; + + status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu); + if (status != 0) { + printk(KERN_ERR "start-cpu failed: %i\n", status); + return 0; + } + + return 1; +} + +static void smp_iic_message_pass(int target, int msg) +{ + unsigned int i; + + if (target < NR_CPUS) { + iic_cause_IPI(target, msg); + } else { + for_each_online_cpu(i) { + if (target == MSG_ALL_BUT_SELF + && i == smp_processor_id()) + continue; + iic_cause_IPI(i, msg); + } + } +} + +static int __init smp_iic_probe(void) +{ + iic_request_IPIs(); + + return cpus_weight(cpu_possible_map); +} + +static void __devinit smp_iic_setup_cpu(int cpu) +{ + if (cpu != boot_cpuid) + iic_setup_cpu(); +} + +static DEFINE_SPINLOCK(timebase_lock); +static unsigned long timebase = 0; + +static void __devinit cell_give_timebase(void) +{ + spin_lock(&timebase_lock); + rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); + timebase = get_tb(); + spin_unlock(&timebase_lock); + + while (timebase) + barrier(); + rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); +} + +static void __devinit cell_take_timebase(void) +{ + while (!timebase) + barrier(); + spin_lock(&timebase_lock); + set_tb(timebase >> 32, timebase & 0xffffffff); + timebase = 0; + spin_unlock(&timebase_lock); +} + +static void __devinit smp_cell_kick_cpu(int nr) +{ + BUG_ON(nr < 0 || nr >= NR_CPUS); + + if (!smp_startup_cpu(nr)) + return; + + /* + * The processor is currently spinning, waiting for the + * cpu_start field to become non-zero After we set cpu_start, + * the processor will continue on to secondary_start + */ + paca[nr].cpu_start = 1; +} + +static int smp_cell_cpu_bootable(unsigned int nr) +{ + /* Special case - we inhibit secondary thread startup + * during boot if the user requests it. Odd-numbered + * cpus are assumed to be secondary threads. + */ + if (system_state < SYSTEM_RUNNING && + cpu_has_feature(CPU_FTR_SMT) && + !smt_enabled_at_boot && nr % 2 != 0) + return 0; + + return 1; +} +static struct smp_ops_t bpa_iic_smp_ops = { + .message_pass = smp_iic_message_pass, + .probe = smp_iic_probe, + .kick_cpu = smp_cell_kick_cpu, + .setup_cpu = smp_iic_setup_cpu, + .cpu_bootable = smp_cell_cpu_bootable, +}; + +/* This is called very early */ +void __init smp_init_cell(void) +{ + int i; + + DBG(" -> smp_init_cell()\n"); + + smp_ops = &bpa_iic_smp_ops; + + /* Mark threads which are still spinning in hold loops. */ + if (cpu_has_feature(CPU_FTR_SMT)) { + for_each_present_cpu(i) { + if (i % 2 == 0) + /* + * Even-numbered logical cpus correspond to + * primary threads. + */ + cpu_set(i, of_spin_map); + } + } else { + of_spin_map = cpu_present_map; + } + + cpu_clear(boot_cpuid, of_spin_map); + + /* Non-lpar has additional take/give timebase */ + if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { + smp_ops->give_timebase = cell_give_timebase; + smp_ops->take_timebase = cell_take_timebase; + } + + DBG(" <- smp_init_cell()\n"); +} diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h index c5e9052e7967..0f42fcc1900b 100644 --- a/include/asm-ppc64/smp.h +++ b/include/asm-ppc64/smp.h @@ -64,6 +64,7 @@ extern cpumask_t cpu_sibling_map[NR_CPUS]; void smp_init_iSeries(void); void smp_init_pSeries(void); +void smp_init_cell(void); extern int __cpu_disable(void); extern void __cpu_die(unsigned int cpu); -- cgit v1.2.3 From e9add2eeb182e2bf1863c548f7a8173c45b4b92f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 Oct 2005 20:08:39 -0500 Subject: [PATCH] powerpc: move rtas_fw.c out of platforms/pseries Cell uses the same code as pSeries for flashing the firmware through rtas, so the implementation should not be part of platforms/pseries. Put it into arch/powerpc/kernel instead. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 7 ++ arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/rtas_fw.c | 136 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/Makefile | 2 +- arch/powerpc/platforms/pseries/rtas-fw.c | 138 ------------------------------- arch/powerpc/platforms/pseries/rtas-fw.h | 3 - include/asm-powerpc/rtas.h | 3 + 7 files changed, 148 insertions(+), 142 deletions(-) create mode 100644 arch/powerpc/kernel/rtas_fw.c delete mode 100644 arch/powerpc/platforms/pseries/rtas-fw.c delete mode 100644 arch/powerpc/platforms/pseries/rtas-fw.h (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 0bd315de156b..aa13a9d95ea2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -278,6 +278,7 @@ config PPC_PSERIES select PPC_I8259 select PPC_RTAS select RTAS_ERROR_LOGGING + select RTAS_FW default y config PPC_CHRP @@ -323,6 +324,7 @@ config PPC_CELL bool " Cell Broadband Processor Architecture" depends on PPC_MULTIPLATFORM && PPC64 select PPC_RTAS + select RTAS_FW config PPC_OF bool @@ -353,6 +355,11 @@ config RTAS_ERROR_LOGGING depends on PPC_RTAS default n +config RTAS_FW + bool + depends on PPC_RTAS + default n + config MPIC_BROKEN_U3 bool depends on PPC_MAPLE diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 572d4f5eaacb..abad3059a21a 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_POWER4) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o obj-$(CONFIG_PPC_RTAS) += rtas.o +obj-$(CONFIG_RTAS_FW) += rtas_fw.o obj-$(CONFIG_IBMVIO) += vio.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/rtas_fw.c b/arch/powerpc/kernel/rtas_fw.c new file mode 100644 index 000000000000..448922e8af1b --- /dev/null +++ b/arch/powerpc/kernel/rtas_fw.c @@ -0,0 +1,136 @@ +/* + * + * Procedures for firmware flash updates. + * + * Peter Bergner, IBM March 2001. + * Copyright (C) 2001 IBM. + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; + +#define FLASH_BLOCK_LIST_VERSION (1UL) + +static void rtas_flash_firmware(void) +{ + unsigned long image_size; + struct flash_block_list *f, *next, *flist; + unsigned long rtas_block_list; + int i, status, update_token; + + update_token = rtas_token("ibm,update-flash-64-and-reboot"); + if (update_token == RTAS_UNKNOWN_SERVICE) { + printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n"); + printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); + return; + } + + /* NOTE: the "first" block list is a global var with no data + * blocks in the kernel data segment. We do this because + * we want to ensure this block_list addr is under 4GB. + */ + rtas_firmware_flash_list.num_blocks = 0; + flist = (struct flash_block_list *)&rtas_firmware_flash_list; + rtas_block_list = virt_to_abs(flist); + if (rtas_block_list >= 4UL*1024*1024*1024) { + printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); + return; + } + + printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); + /* Update the block_list in place. */ + image_size = 0; + for (f = flist; f; f = next) { + /* Translate data addrs to absolute */ + for (i = 0; i < f->num_blocks; i++) { + f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); + image_size += f->blocks[i].length; + } + next = f->next; + /* Don't translate NULL pointer for last entry */ + if (f->next) + f->next = (struct flash_block_list *)virt_to_abs(f->next); + else + f->next = NULL; + /* make num_blocks into the version/length field */ + f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); + } + + printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); + printk(KERN_ALERT "FLASH: performing flash and reboot\n"); + rtas_progress("Flashing \n", 0x0); + rtas_progress("Please Wait... ", 0x0); + printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); + status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); + switch (status) { /* should only get "bad" status */ + case 0: + printk(KERN_ALERT "FLASH: success\n"); + break; + case -1: + printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); + break; + case -3: + printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); + break; + case -4: + printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); + break; + default: + printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); + break; + } +} + +void rtas_flash_bypass_warning(void) +{ + printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); + printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); +} + + +void rtas_fw_restart(char *cmd) +{ + if (rtas_firmware_flash_list.next) + rtas_flash_firmware(); + rtas_restart(cmd); +} + +void rtas_fw_power_off(void) +{ + if (rtas_firmware_flash_list.next) + rtas_flash_bypass_warning(); + rtas_power_off(); +} + +void rtas_fw_halt(void) +{ + if (rtas_firmware_flash_list.next) + rtas_flash_bypass_warning(); + rtas_halt(); +} + +EXPORT_SYMBOL(rtas_firmware_flash_list); diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 5ef494e3a70f..91909a844736 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,5 +1,5 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o rtas-fw.o ras.o + setup.o iommu.o ras.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o diff --git a/arch/powerpc/platforms/pseries/rtas-fw.c b/arch/powerpc/platforms/pseries/rtas-fw.c deleted file mode 100644 index 15d81d758ca0..000000000000 --- a/arch/powerpc/platforms/pseries/rtas-fw.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Procedures for firmware flash updates on pSeries systems. - * - * Peter Bergner, IBM March 2001. - * Copyright (C) 2001 IBM. - * - * 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtas-fw.h" - -struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; - -#define FLASH_BLOCK_LIST_VERSION (1UL) - -static void rtas_flash_firmware(void) -{ - unsigned long image_size; - struct flash_block_list *f, *next, *flist; - unsigned long rtas_block_list; - int i, status, update_token; - - update_token = rtas_token("ibm,update-flash-64-and-reboot"); - if (update_token == RTAS_UNKNOWN_SERVICE) { - printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n"); - printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); - return; - } - - /* NOTE: the "first" block list is a global var with no data - * blocks in the kernel data segment. We do this because - * we want to ensure this block_list addr is under 4GB. - */ - rtas_firmware_flash_list.num_blocks = 0; - flist = (struct flash_block_list *)&rtas_firmware_flash_list; - rtas_block_list = virt_to_abs(flist); - if (rtas_block_list >= 4UL*1024*1024*1024) { - printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); - return; - } - - printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); - /* Update the block_list in place. */ - image_size = 0; - for (f = flist; f; f = next) { - /* Translate data addrs to absolute */ - for (i = 0; i < f->num_blocks; i++) { - f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); - image_size += f->blocks[i].length; - } - next = f->next; - /* Don't translate NULL pointer for last entry */ - if (f->next) - f->next = (struct flash_block_list *)virt_to_abs(f->next); - else - f->next = NULL; - /* make num_blocks into the version/length field */ - f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); - } - - printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); - printk(KERN_ALERT "FLASH: performing flash and reboot\n"); - rtas_progress("Flashing \n", 0x0); - rtas_progress("Please Wait... ", 0x0); - printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); - status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); - switch (status) { /* should only get "bad" status */ - case 0: - printk(KERN_ALERT "FLASH: success\n"); - break; - case -1: - printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); - break; - case -3: - printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); - break; - case -4: - printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); - break; - default: - printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); - break; - } -} - -void rtas_flash_bypass_warning(void) -{ - printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); - printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); -} - - -void rtas_fw_restart(char *cmd) -{ - if (rtas_firmware_flash_list.next) - rtas_flash_firmware(); - rtas_restart(cmd); -} - -void rtas_fw_power_off(void) -{ - if (rtas_firmware_flash_list.next) - rtas_flash_bypass_warning(); - rtas_power_off(); -} - -void rtas_fw_halt(void) -{ - if (rtas_firmware_flash_list.next) - rtas_flash_bypass_warning(); - rtas_halt(); -} - -EXPORT_SYMBOL(rtas_firmware_flash_list); diff --git a/arch/powerpc/platforms/pseries/rtas-fw.h b/arch/powerpc/platforms/pseries/rtas-fw.h deleted file mode 100644 index e70fa69974a3..000000000000 --- a/arch/powerpc/platforms/pseries/rtas-fw.h +++ /dev/null @@ -1,3 +0,0 @@ -void rtas_fw_restart(char *cmd); -void rtas_fw_power_off(void); -void rtas_fw_halt(void); diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index 2c050332471d..d9fd7866927f 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -171,6 +171,9 @@ struct flash_block_list_header { /* just the header of flash_block_list */ struct flash_block_list *next; }; extern struct flash_block_list_header rtas_firmware_flash_list; +void rtas_fw_restart(char *cmd); +void rtas_fw_power_off(void); +void rtas_fw_halt(void); extern struct rtas_t rtas; -- cgit v1.2.3 From 031ef0a72aa8f7ee63ae9f307c1bcff92b3ccc2c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 1 Nov 2005 16:53:24 +1100 Subject: [PATCH] powerpc: Merge ipcbuf.h This patch merges ppc32 and ppc64 versions of ipcbuf.h. The merge is essentially trivial, since the structure defined in each version was already identical. Only wrinkle is that the merged version now includes linux/types.h in order to get the fixed width integer types. In fact, the old versions probably should have been including that anyway, since the file uses various __kernel_*_t types. Built and booted on G5, built for 32-bit pmac, but not booted, since the merge tree currently doesn't boot there. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/ipcbuf.h | 34 ++++++++++++++++++++++++++++++++++ include/asm-ppc/ipcbuf.h | 29 ----------------------------- include/asm-ppc64/ipcbuf.h | 28 ---------------------------- 3 files changed, 34 insertions(+), 57 deletions(-) create mode 100644 include/asm-powerpc/ipcbuf.h delete mode 100644 include/asm-ppc/ipcbuf.h delete mode 100644 include/asm-ppc64/ipcbuf.h (limited to 'include') diff --git a/include/asm-powerpc/ipcbuf.h b/include/asm-powerpc/ipcbuf.h new file mode 100644 index 000000000000..dc0f4d16d05e --- /dev/null +++ b/include/asm-powerpc/ipcbuf.h @@ -0,0 +1,34 @@ +#ifndef _ASM_POWERPC_IPCBUF_H +#define _ASM_POWERPC_IPCBUF_H + +/* + * The ipc64_perm structure for the powerpc is identical to + * kern_ipc_perm as we have always had 32-bit UIDs and GIDs in the + * kernel. Note extra padding because this structure is passed back + * and forth between kernel and user space. Pad space is left for: + * - 1 32-bit value to fill up for 8-byte alignment + * - 2 miscellaneous 64-bit values + * + * 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 + +struct ipc64_perm +{ + __kernel_key_t key; + __kernel_uid_t uid; + __kernel_gid_t gid; + __kernel_uid_t cuid; + __kernel_gid_t cgid; + __kernel_mode_t mode; + unsigned int seq; + unsigned int __pad1; + u64 __unused1; + u64 __unused2; +}; + +#endif /* _ASM_POWERPC_IPCBUF_H */ diff --git a/include/asm-ppc/ipcbuf.h b/include/asm-ppc/ipcbuf.h deleted file mode 100644 index fab6752c7480..000000000000 --- a/include/asm-ppc/ipcbuf.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __PPC_IPCBUF_H__ -#define __PPC_IPCBUF_H__ - -/* - * The ipc64_perm structure for PPC architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 1 32-bit value to fill up for 8-byte alignment - * - 2 miscellaneous 64-bit values (so that this structure matches - * PPC64 ipc64_perm) - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned long seq; - unsigned int __pad2; - unsigned long long __unused1; - unsigned long long __unused2; -}; - -#endif /* __PPC_IPCBUF_H__ */ diff --git a/include/asm-ppc64/ipcbuf.h b/include/asm-ppc64/ipcbuf.h deleted file mode 100644 index fa393c8342af..000000000000 --- a/include/asm-ppc64/ipcbuf.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __PPC64_IPCBUF_H__ -#define __PPC64_IPCBUF_H__ - -/* - * The ipc64_perm structure for the PPC is identical to kern_ipc_perm - * as we have always had 32-bit UIDs and GIDs in the kernel. - * - * 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. - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned int seq; - unsigned int __pad1; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* __PPC64_IPCBUF_H__ */ -- cgit v1.2.3 From a0e60b2033b30a6bb8479629001cf98e58e4079a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 1 Nov 2005 17:28:10 +1100 Subject: [PATCH] powerpc: Merge bitops.h Here's a revised version. This re-introduces the set_bits() function from ppc64, which I removed because I thought it was unused (it exists on no other arch). In fact it is used in the powermac interrupt code (but not on pSeries). - We use LARXL/STCXL macros to generate the right (32 or 64 bit) instructions, similar to LDL/STL from ppc_asm.h, used in fpu.S - ppc32 previously used a full "sync" barrier at the end of test_and_*_bit(), whereas ppc64 used an "isync". The merged version uses "isync", since I believe that's sufficient. - The ppc64 versions of then minix_*() bitmap functions have changed semantics. Previously on ppc64, these functions were big-endian (that is bit 0 was the LSB in the first 64-bit, big-endian word). On ppc32 (and x86, for that matter, they were little-endian. As far as I can tell, the big-endian usage was simply wrong - I guess no-one ever tried to use minixfs on ppc64. - On ppc32 find_next_bit() and find_next_zero_bit() are no longer inline (they were already out-of-line on ppc64). - For ppc64, sched_find_first_bit() has moved from mmu_context.h to the merged bitops. What it was doing in mmu_context.h in the first place, I have no idea. - The fls() function is now implemented using the cntlzw instruction on ppc64, instead of generic_fls(), as it already was on ppc32. - For ARCH=ppc, this patch requires adding arch/powerpc/lib to the arch/ppc/Makefile. This in turn requires some changes to arch/powerpc/lib/Makefile which didn't correctly handle ARCH=ppc. Built and running on G5. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ppc_ksyms.c | 9 - arch/powerpc/lib/Makefile | 9 +- arch/powerpc/lib/bitops.c | 150 +++++++++++++ arch/ppc/Makefile | 3 +- arch/ppc/kernel/bitops.c | 126 ----------- arch/ppc64/kernel/Makefile | 2 +- arch/ppc64/kernel/bitops.c | 147 ------------- include/asm-powerpc/bitops.h | 437 ++++++++++++++++++++++++++++++++++++++ include/asm-ppc/bitops.h | 460 ---------------------------------------- include/asm-ppc64/bitops.h | 360 ------------------------------- include/asm-ppc64/mmu_context.h | 15 -- 11 files changed, 595 insertions(+), 1123 deletions(-) create mode 100644 arch/powerpc/lib/bitops.c delete mode 100644 arch/ppc/kernel/bitops.c delete mode 100644 arch/ppc64/kernel/bitops.c create mode 100644 include/asm-powerpc/bitops.h delete mode 100644 include/asm-ppc/bitops.h delete mode 100644 include/asm-ppc64/bitops.h (limited to 'include') diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 8bc540337ba0..47d6f7e2ea9f 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -81,15 +81,6 @@ EXPORT_SYMBOL(_prep_type); EXPORT_SYMBOL(ucSystemType); #endif -#if !defined(__INLINE_BITOPS) -EXPORT_SYMBOL(set_bit); -EXPORT_SYMBOL(clear_bit); -EXPORT_SYMBOL(change_bit); -EXPORT_SYMBOL(test_and_set_bit); -EXPORT_SYMBOL(test_and_clear_bit); -EXPORT_SYMBOL(test_and_change_bit); -#endif /* __INLINE_BITOPS */ - EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strcat); diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index dfb33915ad61..34f5c2e074c9 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -3,13 +3,14 @@ # ifeq ($(CONFIG_PPC_MERGE),y) -obj-y := string.o +obj-y := string.o strcase.o +obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o endif -obj-y += strcase.o -obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o +obj-y += bitops.o obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ - memcpy_64.o usercopy_64.o mem_64.o string.o + memcpy_64.o usercopy_64.o mem_64.o string.o \ + strcase.o obj-$(CONFIG_PPC_ISERIES) += e2a.o obj-$(CONFIG_XMON) += sstep.o diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c new file mode 100644 index 000000000000..b67ce3004ebf --- /dev/null +++ b/arch/powerpc/lib/bitops.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include + +/** + * find_next_bit - find the next set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < BITS_PER_LONG) + goto found_first; + if (tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if ((tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (64 - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __ffs(tmp); +} +EXPORT_SYMBOL(find_next_bit); + +/* + * This implementation of find_{first,next}_zero_bit was stolen from + * Linus' asm-alpha/bitops.h. + */ +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (BITS_PER_LONG - offset); + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if (~(tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} +EXPORT_SYMBOL(find_next_zero_bit); + +static inline unsigned int ext2_ilog2(unsigned int x) +{ + int lz; + + asm("cntlzw %0,%1": "=r"(lz):"r"(x)); + return 31 - lz; +} + +static inline unsigned int ext2_ffz(unsigned int x) +{ + u32 rc; + if ((x = ~x) == 0) + return 32; + rc = ext2_ilog2(x & -x); + return rc; +} + +unsigned long find_next_zero_le_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) +{ + const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5); + unsigned int result = offset & ~31; + unsigned int tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31; + if (offset) { + tmp = cpu_to_le32p(p++); + tmp |= ~0U >> (32 - offset); /* bug or feature ? */ + if (size < 32) + goto found_first; + if (tmp != ~0) + goto found_middle; + size -= 32; + result += 32; + } + while (size >= 32) { + if ((tmp = cpu_to_le32p(p++)) != ~0) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = cpu_to_le32p(p); +found_first: + tmp |= ~0 << size; + if (tmp == ~0) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ext2_ffz(tmp); +} +EXPORT_SYMBOL(find_next_zero_le_bit); diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 94d5716fa7c3..e719a4933af1 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -66,7 +66,8 @@ head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \ arch/ppc/platforms/ \ arch/ppc/mm/ arch/ppc/lib/ \ - arch/ppc/syslib/ arch/powerpc/sysdev/ + arch/ppc/syslib/ arch/powerpc/sysdev/ \ + arch/powerpc/lib/ core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/ core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/ core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/ diff --git a/arch/ppc/kernel/bitops.c b/arch/ppc/kernel/bitops.c deleted file mode 100644 index 7f53d193968b..000000000000 --- a/arch/ppc/kernel/bitops.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 1996 Paul Mackerras. - */ - -#include -#include - -/* - * If the bitops are not inlined in bitops.h, they are defined here. - * -- paulus - */ -#if !__INLINE_BITOPS -void set_bit(int nr, volatile void * addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%3 \n\ - or %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc" ); -} - -void clear_bit(int nr, volatile void *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%3 \n\ - andc %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -void change_bit(int nr, volatile void *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%3 \n\ - xor %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -int test_and_set_bit(int nr, volatile void *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - or %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); - - return (old & mask) != 0; -} - -int test_and_clear_bit(int nr, volatile void *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - andc %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); - - return (old & mask) != 0; -} - -int test_and_change_bit(int nr, volatile void *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - xor %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); - - return (old & mask) != 0; -} -#endif /* !__INLINE_BITOPS */ diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 247d2fc6a8ed..990df0905c87 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -13,7 +13,7 @@ endif obj-y += irq.o idle.o dma.o \ signal.o \ - align.o bitops.o pacaData.o \ + align.o pacaData.o \ udbg.o ioctl32.o \ rtc.o \ cpu_setup_power4.o \ diff --git a/arch/ppc64/kernel/bitops.c b/arch/ppc64/kernel/bitops.c deleted file mode 100644 index ae329e8b4acb..000000000000 --- a/arch/ppc64/kernel/bitops.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * These are too big to be inlined. - */ - -#include -#include -#include -#include - -unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (64 - offset); - if (size < 64) - goto found_first; - if (~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -EXPORT_SYMBOL(find_next_zero_bit); - -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < 64) - goto found_first; - if (tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if ((tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (64 - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} - -EXPORT_SYMBOL(find_next_bit); - -static inline unsigned int ext2_ilog2(unsigned int x) -{ - int lz; - - asm("cntlzw %0,%1": "=r"(lz):"r"(x)); - return 31 - lz; -} - -static inline unsigned int ext2_ffz(unsigned int x) -{ - u32 rc; - if ((x = ~x) == 0) - return 32; - rc = ext2_ilog2(x & -x); - return rc; -} - -unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5); - unsigned int result = offset & ~31; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31; - if (offset) { - tmp = cpu_to_le32p(p++); - tmp |= ~0U >> (32 - offset); /* bug or feature ? */ - if (size < 32) - goto found_first; - if (tmp != ~0) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = cpu_to_le32p(p++)) != ~0) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = cpu_to_le32p(p); -found_first: - tmp |= ~0 << size; - if (tmp == ~0) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ext2_ffz(tmp); -} - -EXPORT_SYMBOL(find_next_zero_le_bit); diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h new file mode 100644 index 000000000000..dc25c53704d5 --- /dev/null +++ b/include/asm-powerpc/bitops.h @@ -0,0 +1,437 @@ +/* + * PowerPC atomic bit operations. + * + * Merged version by David Gibson . + * Based on ppc64 versions by: Dave Engebretsen, Todd Inglett, Don + * Reed, Pat McCarthy, Peter Bergner, Anton Blanchard. They + * originally took it from the ppc32 code. + * + * Within a word, bits are numbered LSB first. Lot's of places make + * this assumption by directly testing bits with (val & (1< 1 word) bitmaps on a + * big-endian system because, unlike little endian, the number of each + * bit depends on the word size. + * + * The bitop functions are defined to work on unsigned longs, so for a + * ppc64 system the bits end up numbered: + * |63..............0|127............64|191...........128|255...........196| + * and on ppc32: + * |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224| + * + * There are a few little-endian macros used mostly for filesystem + * bitmaps, these work on similar bit arrays layouts, but + * byte-oriented: + * |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56| + * + * The main difference is that bit 3-5 (64b) or 3-4 (32b) in the bit + * number field needs to be reversed compared to the big-endian bit + * fields. This can be achieved by XOR with 0x38 (64b) or 0x18 (32b). + * + * 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. + */ + +#ifndef _ASM_POWERPC_BITOPS_H +#define _ASM_POWERPC_BITOPS_H + +#ifdef __KERNEL__ + +#include +#include +#include + +/* + * clear_bit doesn't imply a memory barrier + */ +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() smp_mb() + +#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) + +#ifdef CONFIG_PPC64 +#define LARXL "ldarx" +#define STCXL "stdcx." +#define CNTLZL "cntlzd" +#else +#define LARXL "lwarx" +#define STCXL "stwcx." +#define CNTLZL "cntlzw" +#endif + +static __inline__ void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "or %0,%0,%2\n" + PPC405_ERR77(0,%3) + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r"(old), "=m"(*p) + : "r"(mask), "r"(p), "m"(*p) + : "cc" ); +} + +static __inline__ void clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "andc %0,%0,%2\n" + PPC405_ERR77(0,%3) + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r"(old), "=m"(*p) + : "r"(mask), "r"(p), "m"(*p) + : "cc" ); +} + +static __inline__ void change_bit(int nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "xor %0,%0,%2\n" + PPC405_ERR77(0,%3) + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r"(old), "=m"(*p) + : "r"(mask), "r"(p), "m"(*p) + : "cc" ); +} + +static __inline__ int test_and_set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1:" LARXL " %0,0,%3 # test_and_set_bit\n" + "or %1,%0,%2 \n" + PPC405_ERR77(0,%3) + STCXL " %1,0,%3 \n" + "bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ int test_and_clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1:" LARXL " %0,0,%3 # test_and_clear_bit\n" + "andc %1,%0,%2 \n" + PPC405_ERR77(0,%3) + STCXL " %1,0,%3 \n" + "bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ int test_and_change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1:" LARXL " %0,0,%3 # test_and_change_bit\n" + "xor %1,%0,%2 \n" + PPC405_ERR77(0,%3) + STCXL " %1,0,%3 \n" + "bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ void set_bits(unsigned long mask, unsigned long *addr) +{ + unsigned long old; + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "or %0,%0,%2\n" + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r" (old), "=m" (*addr) + : "r" (mask), "r" (addr), "m" (*addr) + : "cc"); +} + +/* Non-atomic versions */ +static __inline__ int test_bit(unsigned long nr, + __const__ volatile unsigned long *addr) +{ + return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} + +static __inline__ void __set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + *p |= mask; +} + +static __inline__ void __clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + *p &= ~mask; +} + +static __inline__ void __change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + *p ^= mask; +} + +static __inline__ int __test_and_set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + unsigned long old = *p; + + *p = old | mask; + return (old & mask) != 0; +} + +static __inline__ int __test_and_clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + unsigned long old = *p; + + *p = old & ~mask; + return (old & mask) != 0; +} + +static __inline__ int __test_and_change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + unsigned long old = *p; + + *p = old ^ mask; + return (old & mask) != 0; +} + +/* + * Return the zero-based bit position (LE, not IBM bit numbering) of + * the most significant 1-bit in a double word. + */ +static __inline__ int __ilog2(unsigned long x) +{ + int lz; + + asm (CNTLZL " %0,%1" : "=r" (lz) : "r" (x)); + return BITS_PER_LONG - 1 - lz; +} + +/* + * Determines the bit position of the least significant 0 bit in the + * specified double word. The returned bit position will be + * zero-based, starting from the right side (63/31 - 0). + */ +static __inline__ unsigned long ffz(unsigned long x) +{ + /* no zero exists anywhere in the 8 byte area. */ + if ((x = ~x) == 0) + return BITS_PER_LONG; + + /* + * Calculate the bit position of the least signficant '1' bit in x + * (since x has been changed this will actually be the least signficant + * '0' bit in * the original x). Note: (x & -x) gives us a mask that + * is the least significant * (RIGHT-most) 1-bit of the value in x. + */ + return __ilog2(x & -x); +} + +static __inline__ int __ffs(unsigned long x) +{ + return __ilog2(x & -x); +} + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static __inline__ int ffs(int x) +{ + unsigned long i = (unsigned long)x; + return __ilog2(i & -i) + 1; +} + +/* + * fls: find last (most-significant) bit set. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +static __inline__ int fls(unsigned int x) +{ + int lz; + + asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); + return 32 - lz; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ +#define hweight64(x) generic_hweight64(x) +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) +unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); +/** + * find_first_bit - find the first set bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first set bit, not the number of the byte + * containing a bit. + */ +#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) +unsigned long find_next_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); + +/* Little-endian versions */ + +static __inline__ int test_le_bit(unsigned long nr, + __const__ unsigned long *addr) +{ + __const__ unsigned char *tmp = (__const__ unsigned char *) addr; + return (tmp[nr >> 3] >> (nr & 7)) & 1; +} + +#define __set_le_bit(nr, addr) \ + __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define __clear_le_bit(nr, addr) \ + __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) + +#define test_and_set_le_bit(nr, addr) \ + test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define test_and_clear_le_bit(nr, addr) \ + test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) + +#define __test_and_set_le_bit(nr, addr) \ + __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define __test_and_clear_le_bit(nr, addr) \ + __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) + +#define find_first_zero_le_bit(addr, size) find_next_zero_le_bit((addr), (size), 0) +unsigned long find_next_zero_le_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); + +/* Bitmap functions for the ext2 filesystem */ + +#define ext2_set_bit(nr,addr) \ + __test_and_set_le_bit((nr), (unsigned long*)addr) +#define ext2_clear_bit(nr, addr) \ + __test_and_clear_le_bit((nr), (unsigned long*)addr) + +#define ext2_set_bit_atomic(lock, nr, addr) \ + test_and_set_le_bit((nr), (unsigned long*)addr) +#define ext2_clear_bit_atomic(lock, nr, addr) \ + test_and_clear_le_bit((nr), (unsigned long*)addr) + +#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) + +#define ext2_find_first_zero_bit(addr, size) \ + find_first_zero_le_bit((unsigned long*)addr, size) +#define ext2_find_next_zero_bit(addr, size, off) \ + find_next_zero_le_bit((unsigned long*)addr, size, off) + +/* Bitmap functions for the minix filesystem. */ + +#define minix_test_and_set_bit(nr,addr) \ + __test_and_set_le_bit(nr, (unsigned long *)addr) +#define minix_set_bit(nr,addr) \ + __set_le_bit(nr, (unsigned long *)addr) +#define minix_test_and_clear_bit(nr,addr) \ + __test_and_clear_le_bit(nr, (unsigned long *)addr) +#define minix_test_bit(nr,addr) \ + test_le_bit(nr, (unsigned long *)addr) + +#define minix_find_first_zero_bit(addr,size) \ + find_first_zero_le_bit((unsigned long *)addr, size) + +/* + * Every architecture must define this function. It's the fastest + * way of searching a 140-bit bitmap where the first 100 bits are + * unlikely to be set. It's guaranteed that at least one of the 140 + * bits is cleared. + */ +static inline int sched_find_first_bit(const unsigned long *b) +{ +#ifdef CONFIG_PPC64 + if (unlikely(b[0])) + return __ffs(b[0]); + if (unlikely(b[1])) + return __ffs(b[1]) + 64; + return __ffs(b[2]) + 128; +#else + if (unlikely(b[0])) + return __ffs(b[0]); + if (unlikely(b[1])) + return __ffs(b[1]) + 32; + if (unlikely(b[2])) + return __ffs(b[2]) + 64; + if (b[3]) + return __ffs(b[3]) + 96; + return __ffs(b[4]) + 128; +#endif +} + +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_BITOPS_H */ diff --git a/include/asm-ppc/bitops.h b/include/asm-ppc/bitops.h deleted file mode 100644 index e30f536fd830..000000000000 --- a/include/asm-ppc/bitops.h +++ /dev/null @@ -1,460 +0,0 @@ -/* - * bitops.h: Bit string operations on the ppc - */ - -#ifdef __KERNEL__ -#ifndef _PPC_BITOPS_H -#define _PPC_BITOPS_H - -#include -#include -#include -#include - -/* - * The test_and_*_bit operations are taken to imply a memory barrier - * on SMP systems. - */ -#ifdef CONFIG_SMP -#define SMP_WMB "eieio\n" -#define SMP_MB "\nsync" -#else -#define SMP_WMB -#define SMP_MB -#endif /* CONFIG_SMP */ - -static __inline__ void set_bit(int nr, volatile unsigned long * addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - or %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc" ); -} - -/* - * non-atomic version - */ -static __inline__ void __set_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - *p |= mask; -} - -/* - * clear_bit doesn't imply a memory barrier - */ -#define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() smp_mb() - -static __inline__ void clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - andc %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -/* - * non-atomic version - */ -static __inline__ void __clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - *p &= ~mask; -} - -static __inline__ void change_bit(int nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - xor %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -/* - * non-atomic version - */ -static __inline__ void __change_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - *p ^= mask; -} - -/* - * test_and_*_bit do imply a memory barrier (?) - */ -static __inline__ int test_and_set_bit(int nr, volatile unsigned long *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - or %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -/* - * non-atomic version - */ -static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - unsigned long old = *p; - - *p = old | mask; - return (old & mask) != 0; -} - -static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - andc %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -/* - * non-atomic version - */ -static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - unsigned long old = *p; - - *p = old & ~mask; - return (old & mask) != 0; -} - -static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - xor %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -/* - * non-atomic version - */ -static __inline__ int __test_and_change_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - unsigned long old = *p; - - *p = old ^ mask; - return (old & mask) != 0; -} - -static __inline__ int test_bit(int nr, __const__ volatile unsigned long *addr) -{ - return ((addr[nr >> 5] >> (nr & 0x1f)) & 1) != 0; -} - -/* Return the bit position of the most significant 1 bit in a word */ -static __inline__ int __ilog2(unsigned long x) -{ - int lz; - - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); - return 31 - lz; -} - -static __inline__ int ffz(unsigned long x) -{ - if ((x = ~x) == 0) - return 32; - return __ilog2(x & -x); -} - -static inline int __ffs(unsigned long x) -{ - return __ilog2(x & -x); -} - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __inline__ int ffs(int x) -{ - return __ilog2(x & -x) + 1; -} - -/* - * fls: find last (most-significant) bit set. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -static __inline__ int fls(unsigned int x) -{ - int lz; - - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); - return 32 - lz; -} - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ - -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -/* - * Find the first bit set in a 140-bit bitmap. - * The first 100 bits are unlikely to be set. - */ -static inline int sched_find_first_bit(const unsigned long *b) -{ - if (unlikely(b[0])) - return __ffs(b[0]); - if (unlikely(b[1])) - return __ffs(b[1]) + 32; - if (unlikely(b[2])) - return __ffs(b[2]) + 64; - if (b[3]) - return __ffs(b[3]) + 96; - return __ffs(b[4]) + 128; -} - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -static __inline__ unsigned long find_next_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - unsigned int *p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = *p++; - tmp &= ~0UL << offset; - if (size < 32) - goto found_first; - if (tmp) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = *p++) != 0) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= ~0UL >> (32 - size); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} - -/** - * find_first_bit - find the first set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit-number of the first set bit, not the number of the byte - * containing a bit. - */ -#define find_first_bit(addr, size) \ - find_next_bit((addr), (size), 0) - -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ -#define find_first_zero_bit(addr, size) \ - find_next_zero_bit((addr), (size), 0) - -static __inline__ unsigned long find_next_zero_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - unsigned int * p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = *p++; - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (tmp != ~0U) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = *p++) != ~0U) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - - -#define ext2_set_bit(nr, addr) __test_and_set_bit((nr) ^ 0x18, (unsigned long *)(addr)) -#define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 0x18, (unsigned long *)(addr)) -#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 0x18, (unsigned long *)(addr)) -#define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 0x18, (unsigned long *)(addr)) - -static __inline__ int ext2_test_bit(int nr, __const__ void * addr) -{ - __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - - return (ADDR[nr >> 3] >> (nr & 7)) & 1; -} - -/* - * This implementation of ext2_find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h and modified for a big-endian machine. - */ - -#define ext2_find_first_zero_bit(addr, size) \ - ext2_find_next_zero_bit((addr), (size), 0) - -static __inline__ unsigned long ext2_find_next_zero_bit(const void *addr, - unsigned long size, unsigned long offset) -{ - unsigned int *p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = cpu_to_le32p(p++); - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (tmp != ~0U) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = cpu_to_le32p(p++)) != ~0U) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = cpu_to_le32p(p); -found_first: - tmp |= ~0U << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -/* Bitmap functions for the minix filesystem. */ -#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr) -#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr)) -#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size) - -#endif /* _PPC_BITOPS_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h deleted file mode 100644 index dbfa42ef4a99..000000000000 --- a/include/asm-ppc64/bitops.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * PowerPC64 atomic bit operations. - * Dave Engebretsen, Todd Inglett, Don Reed, Pat McCarthy, Peter Bergner, - * Anton Blanchard - * - * Originally taken from the 32b PPC code. Modified to use 64b values for - * the various counters & memory references. - * - * Bitops are odd when viewed on big-endian systems. They were designed - * on little endian so the size of the bitset doesn't matter (low order bytes - * come first) as long as the bit in question is valid. - * - * Bits are "tested" often using the C expression (val & (1< - -/* - * clear_bit doesn't imply a memory barrier - */ -#define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() smp_mb() - -static __inline__ int test_bit(unsigned long nr, __const__ volatile unsigned long *addr) -{ - return (1UL & (addr[nr >> 6] >> (nr & 63))); -} - -static __inline__ void set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # set_bit\n\ - or %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -static __inline__ void clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # clear_bit\n\ - andc %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -static __inline__ void change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # change_bit\n\ - xor %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -static __inline__ int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old, t; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: ldarx %0,0,%3 # test_and_set_bit\n\ - or %1,%0,%2 \n\ - stdcx. %1,0,%3 \n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old, t; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: ldarx %0,0,%3 # test_and_clear_bit\n\ - andc %1,%0,%2\n\ - stdcx. %1,0,%3\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old, t; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: ldarx %0,0,%3 # test_and_change_bit\n\ - xor %1,%0,%2\n\ - stdcx. %1,0,%3\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ void set_bits(unsigned long mask, unsigned long *addr) -{ - unsigned long old; - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # set_bit\n\ - or %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*addr) - : "r" (mask), "r" (addr), "m" (*addr) - : "cc"); -} - -/* - * non-atomic versions - */ -static __inline__ void __set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - *p |= mask; -} - -static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - *p &= ~mask; -} - -static __inline__ void __change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - *p ^= mask; -} - -static __inline__ int __test_and_set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - unsigned long old = *p; - - *p = old | mask; - return (old & mask) != 0; -} - -static __inline__ int __test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - unsigned long old = *p; - - *p = old & ~mask; - return (old & mask) != 0; -} - -static __inline__ int __test_and_change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - unsigned long old = *p; - - *p = old ^ mask; - return (old & mask) != 0; -} - -/* - * Return the zero-based bit position (from RIGHT TO LEFT, 63 -> 0) of the - * most significant (left-most) 1-bit in a double word. - */ -static __inline__ int __ilog2(unsigned long x) -{ - int lz; - - asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x)); - return 63 - lz; -} - -/* - * Determines the bit position of the least significant (rightmost) 0 bit - * in the specified double word. The returned bit position will be zero-based, - * starting from the right side (63 - 0). - */ -static __inline__ unsigned long ffz(unsigned long x) -{ - /* no zero exists anywhere in the 8 byte area. */ - if ((x = ~x) == 0) - return 64; - - /* - * Calculate the bit position of the least signficant '1' bit in x - * (since x has been changed this will actually be the least signficant - * '0' bit in * the original x). Note: (x & -x) gives us a mask that - * is the least significant * (RIGHT-most) 1-bit of the value in x. - */ - return __ilog2(x & -x); -} - -static __inline__ int __ffs(unsigned long x) -{ - return __ilog2(x & -x); -} - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __inline__ int ffs(int x) -{ - unsigned long i = (unsigned long)x; - return __ilog2(i & -i) + 1; -} - -/* - * fls: find last (most-significant) bit set. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -#define fls(x) generic_fls(x) - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ -#define hweight64(x) generic_hweight64(x) -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_first_zero_bit(addr, size) \ - find_next_zero_bit((addr), (size), 0) - -extern unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_first_bit(addr, size) \ - find_next_bit((addr), (size), 0) - -extern unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_first_zero_le_bit(addr, size) \ - find_next_zero_le_bit((addr), (size), 0) - -static __inline__ int test_le_bit(unsigned long nr, __const__ unsigned long * addr) -{ - __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - return (ADDR[nr >> 3] >> (nr & 7)) & 1; -} - -#define test_and_clear_le_bit(nr, addr) \ - test_and_clear_bit((nr) ^ 0x38, (addr)) -#define test_and_set_le_bit(nr, addr) \ - test_and_set_bit((nr) ^ 0x38, (addr)) - -/* - * non-atomic versions - */ - -#define __set_le_bit(nr, addr) \ - __set_bit((nr) ^ 0x38, (addr)) -#define __clear_le_bit(nr, addr) \ - __clear_bit((nr) ^ 0x38, (addr)) -#define __test_and_clear_le_bit(nr, addr) \ - __test_and_clear_bit((nr) ^ 0x38, (addr)) -#define __test_and_set_le_bit(nr, addr) \ - __test_and_set_bit((nr) ^ 0x38, (addr)) - -#define ext2_set_bit(nr,addr) \ - __test_and_set_le_bit((nr), (unsigned long*)addr) -#define ext2_clear_bit(nr, addr) \ - __test_and_clear_le_bit((nr), (unsigned long*)addr) - -#define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_le_bit((nr), (unsigned long*)addr) -#define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_le_bit((nr), (unsigned long*)addr) - - -#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) -#define ext2_find_first_zero_bit(addr, size) \ - find_first_zero_le_bit((unsigned long*)addr, size) -#define ext2_find_next_zero_bit(addr, size, off) \ - find_next_zero_le_bit((unsigned long*)addr, size, off) - -#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) -#define minix_set_bit(nr,addr) set_bit(nr,addr) -#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) - -#endif /* __KERNEL__ */ -#endif /* _PPC64_BITOPS_H */ diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index 77a743402db4..820dd729b895 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h @@ -16,21 +16,6 @@ * 2 of the License, or (at your option) any later version. */ -/* - * Every architecture must define this function. It's the fastest - * way of searching a 140-bit bitmap where the first 100 bits are - * unlikely to be set. It's guaranteed that at least one of the 140 - * bits is cleared. - */ -static inline int sched_find_first_bit(unsigned long *b) -{ - if (unlikely(b[0])) - return __ffs(b[0]); - if (unlikely(b[1])) - return __ffs(b[1]) + 64; - return __ffs(b[2]) + 128; -} - static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } -- cgit v1.2.3 From 89003ebf9e6a9ccb2327caf72955edd86b274c14 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 1 Nov 2005 21:54:38 +1100 Subject: powerpc: Fix BUG/WARN macros for 64-bit The bug_entry struct had an int in the middle of pointers and unsigned longs, and the inline asm that generated the bug table entries didn't insert the necessary padding, so the fields following it didn't get initialized properly and an oops resulted. This changes the int field (the line number) to a long so that all the fields are the same size and no padding is required. Signed-off-by: Paul Mackerras --- include/asm-powerpc/bug.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h index e4d028e87020..943e3d7dbcc7 100644 --- a/include/asm-powerpc/bug.h +++ b/include/asm-powerpc/bug.h @@ -13,7 +13,7 @@ #ifdef __powerpc64__ #define BUG_TABLE_ENTRY(label, line, file, func) \ - ".llong " #label "\n .long " #line "\n .llong " #file ", " #func "\n" + ".llong " #label ", " #line ", " #file ", " #func "\n" #define TRAP_OP(ra, rb) "1: tdnei " #ra ", " #rb "\n" #define DATA_TYPE long long #else @@ -25,7 +25,7 @@ struct bug_entry { unsigned long bug_addr; - int line; + long line; const char *file; const char *function; }; -- cgit v1.2.3 From 7b28b0d000eeb62d77add636f5d6eb0da04e48aa Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 1 Nov 2005 13:18:54 -0800 Subject: [IB] ucm: 32/64 compatibility fixes Fix structure layouts to ensure same size on 32-bit and 64-bit architectures. This permits 32-bit userspace apps on a 64-bit kernel. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- include/rdma/ib_user_cm.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h index 3037588b8464..19be116047f6 100644 --- a/include/rdma/ib_user_cm.h +++ b/include/rdma/ib_user_cm.h @@ -38,7 +38,7 @@ #include -#define IB_USER_CM_ABI_VERSION 3 +#define IB_USER_CM_ABI_VERSION 4 enum { IB_USER_CM_CMD_CREATE_ID, @@ -84,6 +84,7 @@ struct ib_ucm_create_id_resp { struct ib_ucm_destroy_id { __u64 response; __u32 id; + __u32 reserved; }; struct ib_ucm_destroy_id_resp { @@ -93,6 +94,7 @@ struct ib_ucm_destroy_id_resp { struct ib_ucm_attr_id { __u64 response; __u32 id; + __u32 reserved; }; struct ib_ucm_attr_id_resp { @@ -164,6 +166,7 @@ struct ib_ucm_listen { __be64 service_id; __be64 service_mask; __u32 id; + __u32 reserved; }; struct ib_ucm_establish { @@ -219,7 +222,7 @@ struct ib_ucm_req { __u8 rnr_retry_count; __u8 max_cm_retries; __u8 srq; - __u8 reserved[1]; + __u8 reserved[5]; }; struct ib_ucm_rep { @@ -236,6 +239,7 @@ struct ib_ucm_rep { __u8 flow_control; __u8 rnr_retry_count; __u8 srq; + __u8 reserved[4]; }; struct ib_ucm_info { @@ -245,7 +249,7 @@ struct ib_ucm_info { __u64 data; __u8 info_len; __u8 data_len; - __u8 reserved[2]; + __u8 reserved[6]; }; struct ib_ucm_mra { @@ -273,6 +277,7 @@ struct ib_ucm_sidr_req { __u16 pkey; __u8 len; __u8 max_cm_retries; + __u8 reserved[4]; }; struct ib_ucm_sidr_rep { @@ -284,7 +289,7 @@ struct ib_ucm_sidr_rep { __u64 data; __u8 info_len; __u8 data_len; - __u8 reserved[2]; + __u8 reserved[6]; }; /* * event notification ABI structures. @@ -295,7 +300,7 @@ struct ib_ucm_event_get { __u64 info; __u8 data_len; __u8 info_len; - __u8 reserved[2]; + __u8 reserved[6]; }; struct ib_ucm_req_event_resp { @@ -315,6 +320,7 @@ struct ib_ucm_req_event_resp { __u8 rnr_retry_count; __u8 srq; __u8 port; + __u8 reserved[7]; }; struct ib_ucm_rep_event_resp { @@ -329,7 +335,7 @@ struct ib_ucm_rep_event_resp { __u8 flow_control; __u8 rnr_retry_count; __u8 srq; - __u8 reserved[1]; + __u8 reserved[5]; }; struct ib_ucm_rej_event_resp { @@ -374,6 +380,7 @@ struct ib_ucm_event_resp { __u32 id; __u32 event; __u32 present; + __u32 reserved; union { struct ib_ucm_req_event_resp req_resp; struct ib_ucm_rep_event_resp rep_resp; -- cgit v1.2.3 From c0a8d05c8a5db835b20a3465b1be1cfe4752a13c Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 11:11:11 +1100 Subject: merge filename and modify references to iseries/hv_call_event.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/lpevents.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- drivers/char/viocons.c | 2 +- drivers/char/viotape.c | 2 +- include/asm-powerpc/iseries/hv_call_event.h | 253 ++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/HvCallEvent.h | 253 ---------------------------- include/asm-ppc64/iSeries/HvLpEvent.h | 2 +- include/asm-ppc64/iSeries/mf.h | 2 +- 8 files changed, 259 insertions(+), 259 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_call_event.h delete mode 100644 include/asm-ppc64/iSeries/HvCallEvent.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index 54c7753dbe05..96aa0dd72fb0 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 1544c6f10a38..2c667b180b1e 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 180507ae590f..ecf5c0953ae4 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 51abd3defc1c..232da8c5e66a 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #define VIOTAPE_VERSION "1.2" diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h new file mode 100644 index 000000000000..5d9a327d0122 --- /dev/null +++ b/include/asm-powerpc/iseries/hv_call_event.h @@ -0,0 +1,253 @@ +/* + * HvCallEvent.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * This file contains the "hypervisor call" interface which is used to + * drive the hypervisor from the OS. + */ +#ifndef _HVCALLEVENT_H +#define _HVCALLEVENT_H + +#include +#include +#include + +struct HvLpEvent; + +typedef u8 HvLpEvent_Type; +typedef u8 HvLpEvent_AckInd; +typedef u8 HvLpEvent_AckType; + +struct HvCallEvent_PackedParms { + u8 xAckType:1; + u8 xAckInd:1; + u8 xRsvd:1; + u8 xTargetLp:5; + u8 xType; + u16 xSubtype; + HvLpInstanceId xSourceInstId; + HvLpInstanceId xTargetInstId; +}; + +typedef u8 HvLpDma_Direction; +typedef u8 HvLpDma_AddressType; + +struct HvCallEvent_PackedDmaParms { + u8 xDirection:1; + u8 xLocalAddrType:1; + u8 xRemoteAddrType:1; + u8 xRsvd1:5; + HvLpIndex xRemoteLp; + u8 xType; + u8 xRsvd2; + HvLpInstanceId xLocalInstId; + HvLpInstanceId xRemoteInstId; +}; + +typedef u64 HvLpEvent_Rc; +typedef u64 HvLpDma_Rc; + +#define HvCallEventAckLpEvent HvCallEvent + 0 +#define HvCallEventCancelLpEvent HvCallEvent + 1 +#define HvCallEventCloseLpEventPath HvCallEvent + 2 +#define HvCallEventDmaBufList HvCallEvent + 3 +#define HvCallEventDmaSingle HvCallEvent + 4 +#define HvCallEventDmaToSp HvCallEvent + 5 +#define HvCallEventGetOverflowLpEvents HvCallEvent + 6 +#define HvCallEventGetSourceLpInstanceId HvCallEvent + 7 +#define HvCallEventGetTargetLpInstanceId HvCallEvent + 8 +#define HvCallEventOpenLpEventPath HvCallEvent + 9 +#define HvCallEventSetLpEventStack HvCallEvent + 10 +#define HvCallEventSignalLpEvent HvCallEvent + 11 +#define HvCallEventSignalLpEventParms HvCallEvent + 12 +#define HvCallEventSetInterLpQueueIndex HvCallEvent + 13 +#define HvCallEventSetLpEventQueueInterruptProc HvCallEvent + 14 +#define HvCallEventRouter15 HvCallEvent + 15 + +static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex) +{ + HvCall1(HvCallEventGetOverflowLpEvents, queueIndex); +} + +static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex) +{ + HvCall1(HvCallEventSetInterLpQueueIndex, queueIndex); +} + +static inline void HvCallEvent_setLpEventStack(u8 queueIndex, + char *eventStackAddr, u32 eventStackSize) +{ + u64 abs_addr; + + abs_addr = virt_to_abs(eventStackAddr); + HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr, + eventStackSize); +} + +static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex, + u16 lpLogicalProcIndex) +{ + HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex, + lpLogicalProcIndex); +} + +static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event) +{ + u64 abs_addr; + +#ifdef DEBUG_SENDEVENT + printk("HvCallEvent_signalLpEvent: *event = %016lx\n ", + (unsigned long)event); +#endif + abs_addr = virt_to_abs(event); + return HvCall1(HvCallEventSignalLpEvent, abs_addr); +} + +static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp, + HvLpEvent_Type type, u16 subtype, HvLpEvent_AckInd ackInd, + HvLpEvent_AckType ackType, HvLpInstanceId sourceInstanceId, + HvLpInstanceId targetInstanceId, u64 correlationToken, + u64 eventData1, u64 eventData2, u64 eventData3, + u64 eventData4, u64 eventData5) +{ + /* Pack the misc bits into a single Dword to pass to PLIC */ + union { + struct HvCallEvent_PackedParms parms; + u64 dword; + } packed; + packed.parms.xAckType = ackType; + packed.parms.xAckInd = ackInd; + packed.parms.xRsvd = 0; + packed.parms.xTargetLp = targetLp; + packed.parms.xType = type; + packed.parms.xSubtype = subtype; + packed.parms.xSourceInstId = sourceInstanceId; + packed.parms.xTargetInstId = targetInstanceId; + + return HvCall7(HvCallEventSignalLpEventParms, packed.dword, + correlationToken, eventData1, eventData2, + eventData3, eventData4, eventData5); +} + +static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event) +{ + u64 abs_addr; + + abs_addr = virt_to_abs(event); + return HvCall1(HvCallEventAckLpEvent, abs_addr); +} + +static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event) +{ + u64 abs_addr; + + abs_addr = virt_to_abs(event); + return HvCall1(HvCallEventCancelLpEvent, abs_addr); +} + +static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId( + HvLpIndex targetLp, HvLpEvent_Type type) +{ + return HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type); +} + +static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId( + HvLpIndex targetLp, HvLpEvent_Type type) +{ + return HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type); +} + +static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp, + HvLpEvent_Type type) +{ + HvCall2(HvCallEventOpenLpEventPath, targetLp, type); +} + +static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp, + HvLpEvent_Type type) +{ + HvCall2(HvCallEventCloseLpEventPath, targetLp, type); +} + +static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type, + HvLpIndex remoteLp, HvLpDma_Direction direction, + HvLpInstanceId localInstanceId, + HvLpInstanceId remoteInstanceId, + HvLpDma_AddressType localAddressType, + HvLpDma_AddressType remoteAddressType, + /* Do these need to be converted to absolute addresses? */ + u64 localBufList, u64 remoteBufList, u32 transferLength) +{ + /* Pack the misc bits into a single Dword to pass to PLIC */ + union { + struct HvCallEvent_PackedDmaParms parms; + u64 dword; + } packed; + + packed.parms.xDirection = direction; + packed.parms.xLocalAddrType = localAddressType; + packed.parms.xRemoteAddrType = remoteAddressType; + packed.parms.xRsvd1 = 0; + packed.parms.xRemoteLp = remoteLp; + packed.parms.xType = type; + packed.parms.xRsvd2 = 0; + packed.parms.xLocalInstId = localInstanceId; + packed.parms.xRemoteInstId = remoteInstanceId; + + return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList, + remoteBufList, transferLength); +} + +static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type, + HvLpIndex remoteLp, HvLpDma_Direction direction, + HvLpInstanceId localInstanceId, + HvLpInstanceId remoteInstanceId, + HvLpDma_AddressType localAddressType, + HvLpDma_AddressType remoteAddressType, + u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength) +{ + /* Pack the misc bits into a single Dword to pass to PLIC */ + union { + struct HvCallEvent_PackedDmaParms parms; + u64 dword; + } packed; + + packed.parms.xDirection = direction; + packed.parms.xLocalAddrType = localAddressType; + packed.parms.xRemoteAddrType = remoteAddressType; + packed.parms.xRsvd1 = 0; + packed.parms.xRemoteLp = remoteLp; + packed.parms.xType = type; + packed.parms.xRsvd2 = 0; + packed.parms.xLocalInstId = localInstanceId; + packed.parms.xRemoteInstId = remoteInstanceId; + + return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword, + localAddrOrTce, remoteAddrOrTce, transferLength); +} + +static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote, + u32 length, HvLpDma_Direction dir) +{ + u64 abs_addr; + + abs_addr = virt_to_abs(local); + return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir); +} + +#endif /* _HVCALLEVENT_H */ diff --git a/include/asm-ppc64/iSeries/HvCallEvent.h b/include/asm-ppc64/iSeries/HvCallEvent.h deleted file mode 100644 index 5d9a327d0122..000000000000 --- a/include/asm-ppc64/iSeries/HvCallEvent.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * HvCallEvent.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * This file contains the "hypervisor call" interface which is used to - * drive the hypervisor from the OS. - */ -#ifndef _HVCALLEVENT_H -#define _HVCALLEVENT_H - -#include -#include -#include - -struct HvLpEvent; - -typedef u8 HvLpEvent_Type; -typedef u8 HvLpEvent_AckInd; -typedef u8 HvLpEvent_AckType; - -struct HvCallEvent_PackedParms { - u8 xAckType:1; - u8 xAckInd:1; - u8 xRsvd:1; - u8 xTargetLp:5; - u8 xType; - u16 xSubtype; - HvLpInstanceId xSourceInstId; - HvLpInstanceId xTargetInstId; -}; - -typedef u8 HvLpDma_Direction; -typedef u8 HvLpDma_AddressType; - -struct HvCallEvent_PackedDmaParms { - u8 xDirection:1; - u8 xLocalAddrType:1; - u8 xRemoteAddrType:1; - u8 xRsvd1:5; - HvLpIndex xRemoteLp; - u8 xType; - u8 xRsvd2; - HvLpInstanceId xLocalInstId; - HvLpInstanceId xRemoteInstId; -}; - -typedef u64 HvLpEvent_Rc; -typedef u64 HvLpDma_Rc; - -#define HvCallEventAckLpEvent HvCallEvent + 0 -#define HvCallEventCancelLpEvent HvCallEvent + 1 -#define HvCallEventCloseLpEventPath HvCallEvent + 2 -#define HvCallEventDmaBufList HvCallEvent + 3 -#define HvCallEventDmaSingle HvCallEvent + 4 -#define HvCallEventDmaToSp HvCallEvent + 5 -#define HvCallEventGetOverflowLpEvents HvCallEvent + 6 -#define HvCallEventGetSourceLpInstanceId HvCallEvent + 7 -#define HvCallEventGetTargetLpInstanceId HvCallEvent + 8 -#define HvCallEventOpenLpEventPath HvCallEvent + 9 -#define HvCallEventSetLpEventStack HvCallEvent + 10 -#define HvCallEventSignalLpEvent HvCallEvent + 11 -#define HvCallEventSignalLpEventParms HvCallEvent + 12 -#define HvCallEventSetInterLpQueueIndex HvCallEvent + 13 -#define HvCallEventSetLpEventQueueInterruptProc HvCallEvent + 14 -#define HvCallEventRouter15 HvCallEvent + 15 - -static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex) -{ - HvCall1(HvCallEventGetOverflowLpEvents, queueIndex); -} - -static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex) -{ - HvCall1(HvCallEventSetInterLpQueueIndex, queueIndex); -} - -static inline void HvCallEvent_setLpEventStack(u8 queueIndex, - char *eventStackAddr, u32 eventStackSize) -{ - u64 abs_addr; - - abs_addr = virt_to_abs(eventStackAddr); - HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr, - eventStackSize); -} - -static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex, - u16 lpLogicalProcIndex) -{ - HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex, - lpLogicalProcIndex); -} - -static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event) -{ - u64 abs_addr; - -#ifdef DEBUG_SENDEVENT - printk("HvCallEvent_signalLpEvent: *event = %016lx\n ", - (unsigned long)event); -#endif - abs_addr = virt_to_abs(event); - return HvCall1(HvCallEventSignalLpEvent, abs_addr); -} - -static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp, - HvLpEvent_Type type, u16 subtype, HvLpEvent_AckInd ackInd, - HvLpEvent_AckType ackType, HvLpInstanceId sourceInstanceId, - HvLpInstanceId targetInstanceId, u64 correlationToken, - u64 eventData1, u64 eventData2, u64 eventData3, - u64 eventData4, u64 eventData5) -{ - /* Pack the misc bits into a single Dword to pass to PLIC */ - union { - struct HvCallEvent_PackedParms parms; - u64 dword; - } packed; - packed.parms.xAckType = ackType; - packed.parms.xAckInd = ackInd; - packed.parms.xRsvd = 0; - packed.parms.xTargetLp = targetLp; - packed.parms.xType = type; - packed.parms.xSubtype = subtype; - packed.parms.xSourceInstId = sourceInstanceId; - packed.parms.xTargetInstId = targetInstanceId; - - return HvCall7(HvCallEventSignalLpEventParms, packed.dword, - correlationToken, eventData1, eventData2, - eventData3, eventData4, eventData5); -} - -static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event) -{ - u64 abs_addr; - - abs_addr = virt_to_abs(event); - return HvCall1(HvCallEventAckLpEvent, abs_addr); -} - -static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event) -{ - u64 abs_addr; - - abs_addr = virt_to_abs(event); - return HvCall1(HvCallEventCancelLpEvent, abs_addr); -} - -static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId( - HvLpIndex targetLp, HvLpEvent_Type type) -{ - return HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type); -} - -static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId( - HvLpIndex targetLp, HvLpEvent_Type type) -{ - return HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type); -} - -static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp, - HvLpEvent_Type type) -{ - HvCall2(HvCallEventOpenLpEventPath, targetLp, type); -} - -static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp, - HvLpEvent_Type type) -{ - HvCall2(HvCallEventCloseLpEventPath, targetLp, type); -} - -static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type, - HvLpIndex remoteLp, HvLpDma_Direction direction, - HvLpInstanceId localInstanceId, - HvLpInstanceId remoteInstanceId, - HvLpDma_AddressType localAddressType, - HvLpDma_AddressType remoteAddressType, - /* Do these need to be converted to absolute addresses? */ - u64 localBufList, u64 remoteBufList, u32 transferLength) -{ - /* Pack the misc bits into a single Dword to pass to PLIC */ - union { - struct HvCallEvent_PackedDmaParms parms; - u64 dword; - } packed; - - packed.parms.xDirection = direction; - packed.parms.xLocalAddrType = localAddressType; - packed.parms.xRemoteAddrType = remoteAddressType; - packed.parms.xRsvd1 = 0; - packed.parms.xRemoteLp = remoteLp; - packed.parms.xType = type; - packed.parms.xRsvd2 = 0; - packed.parms.xLocalInstId = localInstanceId; - packed.parms.xRemoteInstId = remoteInstanceId; - - return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList, - remoteBufList, transferLength); -} - -static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type, - HvLpIndex remoteLp, HvLpDma_Direction direction, - HvLpInstanceId localInstanceId, - HvLpInstanceId remoteInstanceId, - HvLpDma_AddressType localAddressType, - HvLpDma_AddressType remoteAddressType, - u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength) -{ - /* Pack the misc bits into a single Dword to pass to PLIC */ - union { - struct HvCallEvent_PackedDmaParms parms; - u64 dword; - } packed; - - packed.parms.xDirection = direction; - packed.parms.xLocalAddrType = localAddressType; - packed.parms.xRemoteAddrType = remoteAddressType; - packed.parms.xRsvd1 = 0; - packed.parms.xRemoteLp = remoteLp; - packed.parms.xType = type; - packed.parms.xRsvd2 = 0; - packed.parms.xLocalInstId = localInstanceId; - packed.parms.xRemoteInstId = remoteInstanceId; - - return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword, - localAddrOrTce, remoteAddrOrTce, transferLength); -} - -static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote, - u32 length, HvLpDma_Direction dir) -{ - u64 abs_addr; - - abs_addr = virt_to_abs(local); - return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir); -} - -#endif /* _HVCALLEVENT_H */ diff --git a/include/asm-ppc64/iSeries/HvLpEvent.h b/include/asm-ppc64/iSeries/HvLpEvent.h index 865000de79b6..75ff1b3ed2e5 100644 --- a/include/asm-ppc64/iSeries/HvLpEvent.h +++ b/include/asm-ppc64/iSeries/HvLpEvent.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include /* * HvLpEvent is the structure for Lp Event messages passed between diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h index 7e6a0d936999..f84404a07f4b 100644 --- a/include/asm-ppc64/iSeries/mf.h +++ b/include/asm-ppc64/iSeries/mf.h @@ -29,7 +29,7 @@ #include #include -#include +#include struct rtc_time; -- cgit v1.2.3 From 50592f5d2ae7b95b239ea41d76ad81fee046be86 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 11:37:22 +1100 Subject: merge filename and modify references to iseries/hv_call_sc.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/call_hpt.h | 2 +- arch/powerpc/platforms/iseries/call_pci.h | 2 +- arch/powerpc/platforms/iseries/call_sm.h | 2 +- arch/powerpc/platforms/iseries/hvlog.c | 2 +- arch/powerpc/platforms/iseries/ksyms.c | 2 +- include/asm-powerpc/iseries/hv_call.h | 2 +- include/asm-powerpc/iseries/hv_call_event.h | 2 +- include/asm-powerpc/iseries/hv_call_sc.h | 51 +++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/HvCallSc.h | 51 ----------------------------- include/asm-ppc64/iSeries/HvCallXm.h | 2 +- include/asm-ppc64/iSeries/HvLpConfig.h | 2 +- 11 files changed, 60 insertions(+), 60 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_call_sc.h delete mode 100644 include/asm-ppc64/iSeries/HvCallSc.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h index 321f3bb7a8f5..a626d8c289ee 100644 --- a/arch/powerpc/platforms/iseries/call_hpt.h +++ b/arch/powerpc/platforms/iseries/call_hpt.h @@ -23,7 +23,7 @@ * drive the hypervisor from the OS. */ -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h index a86e065b9577..53cc163d4689 100644 --- a/arch/powerpc/platforms/iseries/call_pci.h +++ b/arch/powerpc/platforms/iseries/call_pci.h @@ -25,7 +25,7 @@ #ifndef _PLATFORMS_ISERIES_CALL_PCI_H #define _PLATFORMS_ISERIES_CALL_PCI_H -#include +#include #include /* diff --git a/arch/powerpc/platforms/iseries/call_sm.h b/arch/powerpc/platforms/iseries/call_sm.h index ef223166cf22..a9726822e953 100644 --- a/arch/powerpc/platforms/iseries/call_sm.h +++ b/arch/powerpc/platforms/iseries/call_sm.h @@ -23,7 +23,7 @@ * drive the hypervisor from the OS. */ -#include +#include #include #define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c index 5a89b481f978..48a3f7900389 100644 --- a/arch/powerpc/platforms/iseries/hvlog.c +++ b/arch/powerpc/platforms/iseries/hvlog.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c index f271b3539721..a2200842f4e5 100644 --- a/arch/powerpc/platforms/iseries/ksyms.c +++ b/arch/powerpc/platforms/iseries/ksyms.c @@ -9,7 +9,7 @@ #include #include -#include +#include EXPORT_SYMBOL(HvCall0); EXPORT_SYMBOL(HvCall1); diff --git a/include/asm-powerpc/iseries/hv_call.h b/include/asm-powerpc/iseries/hv_call.h index c3f19475c0d9..5edfe2c8ea33 100644 --- a/include/asm-powerpc/iseries/hv_call.h +++ b/include/asm-powerpc/iseries/hv_call.h @@ -23,7 +23,7 @@ #ifndef _HVCALL_H #define _HVCALL_H -#include +#include #include #include diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h index 5d9a327d0122..202c87c39ef4 100644 --- a/include/asm-powerpc/iseries/hv_call_event.h +++ b/include/asm-powerpc/iseries/hv_call_event.h @@ -23,7 +23,7 @@ #ifndef _HVCALLEVENT_H #define _HVCALLEVENT_H -#include +#include #include #include diff --git a/include/asm-powerpc/iseries/hv_call_sc.h b/include/asm-powerpc/iseries/hv_call_sc.h new file mode 100644 index 000000000000..a62cef3822f9 --- /dev/null +++ b/include/asm-powerpc/iseries/hv_call_sc.h @@ -0,0 +1,51 @@ +/* + * HvCallSc.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVCALLSC_H +#define _HVCALLSC_H + +#include + +#define HvCallBase 0x8000000000000000ul +#define HvCallCc 0x8001000000000000ul +#define HvCallCfg 0x8002000000000000ul +#define HvCallEvent 0x8003000000000000ul +#define HvCallHpt 0x8004000000000000ul +#define HvCallPci 0x8005000000000000ul +#define HvCallSm 0x8007000000000000ul +#define HvCallXm 0x8009000000000000ul + +extern u64 HvCall0(u64); +extern u64 HvCall1(u64, u64); +extern u64 HvCall2(u64, u64, u64); +extern u64 HvCall3(u64, u64, u64, u64); +extern u64 HvCall4(u64, u64, u64, u64, u64); +extern u64 HvCall5(u64, u64, u64, u64, u64, u64); +extern u64 HvCall6(u64, u64, u64, u64, u64, u64, u64); +extern u64 HvCall7(u64, u64, u64, u64, u64, u64, u64, u64); + +extern u64 HvCall0Ret16(u64, void *); +extern u64 HvCall1Ret16(u64, void *, u64); +extern u64 HvCall2Ret16(u64, void *, u64, u64); +extern u64 HvCall3Ret16(u64, void *, u64, u64, u64); +extern u64 HvCall4Ret16(u64, void *, u64, u64, u64, u64); +extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64); +extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64); +extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64); + +#endif /* _HVCALLSC_H */ diff --git a/include/asm-ppc64/iSeries/HvCallSc.h b/include/asm-ppc64/iSeries/HvCallSc.h deleted file mode 100644 index a62cef3822f9..000000000000 --- a/include/asm-ppc64/iSeries/HvCallSc.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * HvCallSc.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _HVCALLSC_H -#define _HVCALLSC_H - -#include - -#define HvCallBase 0x8000000000000000ul -#define HvCallCc 0x8001000000000000ul -#define HvCallCfg 0x8002000000000000ul -#define HvCallEvent 0x8003000000000000ul -#define HvCallHpt 0x8004000000000000ul -#define HvCallPci 0x8005000000000000ul -#define HvCallSm 0x8007000000000000ul -#define HvCallXm 0x8009000000000000ul - -extern u64 HvCall0(u64); -extern u64 HvCall1(u64, u64); -extern u64 HvCall2(u64, u64, u64); -extern u64 HvCall3(u64, u64, u64, u64); -extern u64 HvCall4(u64, u64, u64, u64, u64); -extern u64 HvCall5(u64, u64, u64, u64, u64, u64); -extern u64 HvCall6(u64, u64, u64, u64, u64, u64, u64); -extern u64 HvCall7(u64, u64, u64, u64, u64, u64, u64, u64); - -extern u64 HvCall0Ret16(u64, void *); -extern u64 HvCall1Ret16(u64, void *, u64); -extern u64 HvCall2Ret16(u64, void *, u64, u64); -extern u64 HvCall3Ret16(u64, void *, u64, u64, u64); -extern u64 HvCall4Ret16(u64, void *, u64, u64, u64, u64); -extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64); -extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64); -extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64); - -#endif /* _HVCALLSC_H */ diff --git a/include/asm-ppc64/iSeries/HvCallXm.h b/include/asm-ppc64/iSeries/HvCallXm.h index 8b9ba608daaf..8a7b6e3c01ac 100644 --- a/include/asm-ppc64/iSeries/HvCallXm.h +++ b/include/asm-ppc64/iSeries/HvCallXm.h @@ -5,7 +5,7 @@ #ifndef _HVCALLXM_H #define _HVCALLXM_H -#include +#include #include #define HvCallXmGetTceTableParms HvCallXm + 0 diff --git a/include/asm-ppc64/iSeries/HvLpConfig.h b/include/asm-ppc64/iSeries/HvLpConfig.h index f1cf1e70ca3c..9077fc8e3f6c 100644 --- a/include/asm-ppc64/iSeries/HvLpConfig.h +++ b/include/asm-ppc64/iSeries/HvLpConfig.h @@ -24,7 +24,7 @@ * to determine which resources should be allocated to each partition. */ -#include +#include #include #include -- cgit v1.2.3 From 8021b8a77690d13ffb93eeadb6728e924d700bd5 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 11:41:12 +1100 Subject: merge filename and modify references to iseries/hv_call_xm.h Signed-off-by: Kelly Daly --- arch/powerpc/kernel/time.c | 2 +- arch/powerpc/platforms/iseries/iommu.c | 2 +- arch/powerpc/platforms/iseries/irq.c | 2 +- arch/powerpc/platforms/iseries/pci.c | 2 +- arch/powerpc/platforms/iseries/proc.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/powerpc/platforms/iseries/vio.c | 2 +- include/asm-powerpc/iseries/hv_call_xm.h | 78 ++++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/HvCallXm.h | 78 -------------------------------- 9 files changed, 85 insertions(+), 85 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_call_xm.h delete mode 100644 include/asm-ppc64/iSeries/HvCallXm.h (limited to 'include') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 23436b6c1881..348746c55ebd 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -67,7 +67,7 @@ #endif #ifdef CONFIG_PPC_ISERIES #include -#include +#include #endif /* keep track of when we need to update the rtc */ diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 1db26d8be640..1a6845b5c5a4 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include extern struct list_head iSeries_Global_Device_List; diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 937ac99b9d33..b1aacf64fb8e 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "irq.h" #include "call_pci.h" diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 959e59fd9c11..a39b7a720101 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c index 6f1929cac66b..beba0f62e653 100644 --- a/arch/powerpc/platforms/iseries/proc.c +++ b/arch/powerpc/platforms/iseries/proc.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "processor_vpd.h" #include "main_store.h" diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 2c667b180b1e..669e63174ecc 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index c0f7d2e9153f..c64741e50cb2 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include struct device *iSeries_vio_dev = &vio_bus_device.dev; EXPORT_SYMBOL(iSeries_vio_dev); diff --git a/include/asm-powerpc/iseries/hv_call_xm.h b/include/asm-powerpc/iseries/hv_call_xm.h new file mode 100644 index 000000000000..8a7b6e3c01ac --- /dev/null +++ b/include/asm-powerpc/iseries/hv_call_xm.h @@ -0,0 +1,78 @@ +/* + * This file contains the "hypervisor call" interface which is used to + * drive the hypervisor from SLIC. + */ +#ifndef _HVCALLXM_H +#define _HVCALLXM_H + +#include +#include + +#define HvCallXmGetTceTableParms HvCallXm + 0 +#define HvCallXmTestBus HvCallXm + 1 +#define HvCallXmConnectBusUnit HvCallXm + 2 +#define HvCallXmLoadTod HvCallXm + 8 +#define HvCallXmTestBusUnit HvCallXm + 9 +#define HvCallXmSetTce HvCallXm + 11 +#define HvCallXmSetTces HvCallXm + 13 + +/* + * Structure passed to HvCallXm_getTceTableParms + */ +struct iommu_table_cb { + unsigned long itc_busno; /* Bus number for this tce table */ + unsigned long itc_start; /* Will be NULL for secondary */ + unsigned long itc_totalsize; /* Size (in pages) of whole table */ + unsigned long itc_offset; /* Index into real tce table of the + start of our section */ + unsigned long itc_size; /* Size (in pages) of our section */ + unsigned long itc_index; /* Index of this tce table */ + unsigned short itc_maxtables; /* Max num of tables for partition */ + unsigned char itc_virtbus; /* Flag to indicate virtual bus */ + unsigned char itc_slotno; /* IOA Tce Slot Index */ + unsigned char itc_rsvd[4]; +}; + +static inline void HvCallXm_getTceTableParms(u64 cb) +{ + HvCall1(HvCallXmGetTceTableParms, cb); +} + +static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce) +{ + return HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce); +} + +static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset, + u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4) +{ + return HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces, + tce1, tce2, tce3, tce4); +} + +static inline u64 HvCallXm_testBus(u16 busNumber) +{ + return HvCall1(HvCallXmTestBus, busNumber); +} + +static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber, + u8 deviceId) +{ + return HvCall2(HvCallXmTestBusUnit, busNumber, + (subBusNumber << 8) | deviceId); +} + +static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber, + u8 deviceId, u64 interruptToken) +{ + return HvCall5(HvCallXmConnectBusUnit, busNumber, + (subBusNumber << 8) | deviceId, interruptToken, 0, + 0 /* HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)) */); +} + +static inline u64 HvCallXm_loadTod(void) +{ + return HvCall0(HvCallXmLoadTod); +} + +#endif /* _HVCALLXM_H */ diff --git a/include/asm-ppc64/iSeries/HvCallXm.h b/include/asm-ppc64/iSeries/HvCallXm.h deleted file mode 100644 index 8a7b6e3c01ac..000000000000 --- a/include/asm-ppc64/iSeries/HvCallXm.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file contains the "hypervisor call" interface which is used to - * drive the hypervisor from SLIC. - */ -#ifndef _HVCALLXM_H -#define _HVCALLXM_H - -#include -#include - -#define HvCallXmGetTceTableParms HvCallXm + 0 -#define HvCallXmTestBus HvCallXm + 1 -#define HvCallXmConnectBusUnit HvCallXm + 2 -#define HvCallXmLoadTod HvCallXm + 8 -#define HvCallXmTestBusUnit HvCallXm + 9 -#define HvCallXmSetTce HvCallXm + 11 -#define HvCallXmSetTces HvCallXm + 13 - -/* - * Structure passed to HvCallXm_getTceTableParms - */ -struct iommu_table_cb { - unsigned long itc_busno; /* Bus number for this tce table */ - unsigned long itc_start; /* Will be NULL for secondary */ - unsigned long itc_totalsize; /* Size (in pages) of whole table */ - unsigned long itc_offset; /* Index into real tce table of the - start of our section */ - unsigned long itc_size; /* Size (in pages) of our section */ - unsigned long itc_index; /* Index of this tce table */ - unsigned short itc_maxtables; /* Max num of tables for partition */ - unsigned char itc_virtbus; /* Flag to indicate virtual bus */ - unsigned char itc_slotno; /* IOA Tce Slot Index */ - unsigned char itc_rsvd[4]; -}; - -static inline void HvCallXm_getTceTableParms(u64 cb) -{ - HvCall1(HvCallXmGetTceTableParms, cb); -} - -static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce) -{ - return HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce); -} - -static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset, - u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4) -{ - return HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces, - tce1, tce2, tce3, tce4); -} - -static inline u64 HvCallXm_testBus(u16 busNumber) -{ - return HvCall1(HvCallXmTestBus, busNumber); -} - -static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber, - u8 deviceId) -{ - return HvCall2(HvCallXmTestBusUnit, busNumber, - (subBusNumber << 8) | deviceId); -} - -static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber, - u8 deviceId, u64 interruptToken) -{ - return HvCall5(HvCallXmConnectBusUnit, busNumber, - (subBusNumber << 8) | deviceId, interruptToken, 0, - 0 /* HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)) */); -} - -static inline u64 HvCallXm_loadTod(void) -{ - return HvCall0(HvCallXmLoadTod); -} - -#endif /* _HVCALLXM_H */ -- cgit v1.2.3 From 15b17189489f6d759fa2d61e7b6c87c55eeffb2c Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 11:55:28 +1100 Subject: merge filename and modify reference to iseries/hv_lp_config.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/hvlpconfig.c | 2 +- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/powerpc/platforms/iseries/vio.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 2 +- arch/ppc64/kernel/lparcfg.c | 2 +- drivers/block/viodasd.c | 2 +- drivers/char/viocons.c | 2 +- drivers/char/viotape.c | 2 +- drivers/net/iseries_veth.c | 2 +- drivers/scsi/ibmvscsi/iseries_vscsi.c | 2 +- include/asm-powerpc/iseries/hv_lp_config.h | 138 ++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/HvLpConfig.h | 138 ---------------------------- 13 files changed, 149 insertions(+), 149 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_lp_config.h delete mode 100644 include/asm-ppc64/iSeries/HvLpConfig.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/hvlpconfig.c b/arch/powerpc/platforms/iseries/hvlpconfig.c index dc28621aea0d..663a1affb4bb 100644 --- a/arch/powerpc/platforms/iseries/hvlpconfig.c +++ b/arch/powerpc/platforms/iseries/hvlpconfig.c @@ -17,7 +17,7 @@ */ #include -#include +#include HvLpIndex HvLpConfig_getLpIndex_outline(void) { diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index e5de31aa0015..027df204446d 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include "setup.h" diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 669e63174ecc..638747c772f8 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index c64741e50cb2..4e2dafc83bb2 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include struct device *iSeries_vio_dev = &vio_bus_device.dev; diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index c0c767bd37f1..8e33a90bedb9 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index cae19bbd5acd..e4236f2707e1 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 709f809f79f1..5c907b747648 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include MODULE_DESCRIPTION("iSeries Virtual DASD"); diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index ecf5c0953ae4..33d7820eaab9 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -48,7 +48,7 @@ #include #include -#include +#include #include #ifdef CONFIG_VT diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 232da8c5e66a..296797e5a2b5 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -57,7 +57,7 @@ #include #include #include -#include +#include #define VIOTAPE_VERSION "1.2" #define VIOTAPE_MAXREQ 1 diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index f5ea39ff1017..aaabaf30d4b8 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -75,7 +75,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index e9202f2a8276..c652779c1a32 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include "ibmvscsi.h" diff --git a/include/asm-powerpc/iseries/hv_lp_config.h b/include/asm-powerpc/iseries/hv_lp_config.h new file mode 100644 index 000000000000..9077fc8e3f6c --- /dev/null +++ b/include/asm-powerpc/iseries/hv_lp_config.h @@ -0,0 +1,138 @@ +/* + * HvLpConfig.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVLPCONFIG_H +#define _HVLPCONFIG_H + +/* + * This file contains the interface to the LPAR configuration data + * to determine which resources should be allocated to each partition. + */ + +#include +#include +#include + +enum { + HvCallCfg_Cur = 0, + HvCallCfg_Init = 1, + HvCallCfg_Max = 2, + HvCallCfg_Min = 3 +}; + +#define HvCallCfgGetSystemPhysicalProcessors HvCallCfg + 6 +#define HvCallCfgGetPhysicalProcessors HvCallCfg + 7 +#define HvCallCfgGetMsChunks HvCallCfg + 9 +#define HvCallCfgGetSharedPoolIndex HvCallCfg + 20 +#define HvCallCfgGetSharedProcUnits HvCallCfg + 21 +#define HvCallCfgGetNumProcsInSharedPool HvCallCfg + 22 +#define HvCallCfgGetVirtualLanIndexMap HvCallCfg + 30 +#define HvCallCfgGetHostingLpIndex HvCallCfg + 32 + +extern HvLpIndex HvLpConfig_getLpIndex_outline(void); + +static inline HvLpIndex HvLpConfig_getLpIndex(void) +{ + return itLpNaca.xLpIndex; +} + +static inline HvLpIndex HvLpConfig_getPrimaryLpIndex(void) +{ + return itLpNaca.xPrimaryLpIndex; +} + +static inline u64 HvLpConfig_getMsChunks(void) +{ + return HvCall2(HvCallCfgGetMsChunks, HvLpConfig_getLpIndex(), + HvCallCfg_Cur); +} + +static inline u64 HvLpConfig_getSystemPhysicalProcessors(void) +{ + return HvCall0(HvCallCfgGetSystemPhysicalProcessors); +} + +static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI) +{ + return (u16)HvCall1(HvCallCfgGetNumProcsInSharedPool, sPI); +} + +static inline u64 HvLpConfig_getPhysicalProcessors(void) +{ + return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(), + HvCallCfg_Cur); +} + +static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void) +{ + return HvCall1(HvCallCfgGetSharedPoolIndex, HvLpConfig_getLpIndex()); +} + +static inline u64 HvLpConfig_getSharedProcUnits(void) +{ + return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(), + HvCallCfg_Cur); +} + +static inline u64 HvLpConfig_getMaxSharedProcUnits(void) +{ + return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(), + HvCallCfg_Max); +} + +static inline u64 HvLpConfig_getMaxPhysicalProcessors(void) +{ + return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(), + HvCallCfg_Max); +} + +static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp( + HvLpIndex lp) +{ + /* + * This is a new function in V5R1 so calls to this on older + * hypervisors will return -1 + */ + u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp); + if (retVal == -1) + retVal = 0; + return retVal; +} + +static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void) +{ + return HvLpConfig_getVirtualLanIndexMapForLp( + HvLpConfig_getLpIndex_outline()); +} + +static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1, + HvLpIndex lp2) +{ + HvLpVirtualLanIndexMap virtualLanIndexMap1 = + HvLpConfig_getVirtualLanIndexMapForLp(lp1); + HvLpVirtualLanIndexMap virtualLanIndexMap2 = + HvLpConfig_getVirtualLanIndexMapForLp(lp2); + return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0); +} + +static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp) +{ + return HvCall1(HvCallCfgGetHostingLpIndex, lp); +} + +#endif /* _HVLPCONFIG_H */ diff --git a/include/asm-ppc64/iSeries/HvLpConfig.h b/include/asm-ppc64/iSeries/HvLpConfig.h deleted file mode 100644 index 9077fc8e3f6c..000000000000 --- a/include/asm-ppc64/iSeries/HvLpConfig.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * HvLpConfig.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _HVLPCONFIG_H -#define _HVLPCONFIG_H - -/* - * This file contains the interface to the LPAR configuration data - * to determine which resources should be allocated to each partition. - */ - -#include -#include -#include - -enum { - HvCallCfg_Cur = 0, - HvCallCfg_Init = 1, - HvCallCfg_Max = 2, - HvCallCfg_Min = 3 -}; - -#define HvCallCfgGetSystemPhysicalProcessors HvCallCfg + 6 -#define HvCallCfgGetPhysicalProcessors HvCallCfg + 7 -#define HvCallCfgGetMsChunks HvCallCfg + 9 -#define HvCallCfgGetSharedPoolIndex HvCallCfg + 20 -#define HvCallCfgGetSharedProcUnits HvCallCfg + 21 -#define HvCallCfgGetNumProcsInSharedPool HvCallCfg + 22 -#define HvCallCfgGetVirtualLanIndexMap HvCallCfg + 30 -#define HvCallCfgGetHostingLpIndex HvCallCfg + 32 - -extern HvLpIndex HvLpConfig_getLpIndex_outline(void); - -static inline HvLpIndex HvLpConfig_getLpIndex(void) -{ - return itLpNaca.xLpIndex; -} - -static inline HvLpIndex HvLpConfig_getPrimaryLpIndex(void) -{ - return itLpNaca.xPrimaryLpIndex; -} - -static inline u64 HvLpConfig_getMsChunks(void) -{ - return HvCall2(HvCallCfgGetMsChunks, HvLpConfig_getLpIndex(), - HvCallCfg_Cur); -} - -static inline u64 HvLpConfig_getSystemPhysicalProcessors(void) -{ - return HvCall0(HvCallCfgGetSystemPhysicalProcessors); -} - -static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI) -{ - return (u16)HvCall1(HvCallCfgGetNumProcsInSharedPool, sPI); -} - -static inline u64 HvLpConfig_getPhysicalProcessors(void) -{ - return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(), - HvCallCfg_Cur); -} - -static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void) -{ - return HvCall1(HvCallCfgGetSharedPoolIndex, HvLpConfig_getLpIndex()); -} - -static inline u64 HvLpConfig_getSharedProcUnits(void) -{ - return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(), - HvCallCfg_Cur); -} - -static inline u64 HvLpConfig_getMaxSharedProcUnits(void) -{ - return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(), - HvCallCfg_Max); -} - -static inline u64 HvLpConfig_getMaxPhysicalProcessors(void) -{ - return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(), - HvCallCfg_Max); -} - -static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp( - HvLpIndex lp) -{ - /* - * This is a new function in V5R1 so calls to this on older - * hypervisors will return -1 - */ - u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp); - if (retVal == -1) - retVal = 0; - return retVal; -} - -static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void) -{ - return HvLpConfig_getVirtualLanIndexMapForLp( - HvLpConfig_getLpIndex_outline()); -} - -static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1, - HvLpIndex lp2) -{ - HvLpVirtualLanIndexMap virtualLanIndexMap1 = - HvLpConfig_getVirtualLanIndexMapForLp(lp1); - HvLpVirtualLanIndexMap virtualLanIndexMap2 = - HvLpConfig_getVirtualLanIndexMapForLp(lp2); - return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0); -} - -static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp) -{ - return HvCall1(HvCallCfgGetHostingLpIndex, lp); -} - -#endif /* _HVLPCONFIG_H */ -- cgit v1.2.3 From e45423eac2e191a6cfdacdf61cb931976d73cc0b Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 12:08:31 +1100 Subject: merge filename and modify references to iseries/hv_lp_event.h Signed-off-by: Kelly Daly --- arch/powerpc/kernel/asm-offsets.c | 2 +- arch/powerpc/platforms/iseries/irq.c | 2 +- arch/powerpc/platforms/iseries/lpevents.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 2 +- arch/ppc64/kernel/asm-offsets.c | 2 +- drivers/block/viodasd.c | 2 +- drivers/cdrom/viocd.c | 2 +- drivers/char/viocons.c | 2 +- drivers/char/viotape.c | 2 +- drivers/net/iseries_veth.c | 2 +- drivers/scsi/ibmvscsi/iseries_vscsi.c | 2 +- include/asm-powerpc/iseries/hv_lp_event.h | 142 ++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/HvLpEvent.h | 142 ------------------------------ include/asm-ppc64/iSeries/vio.h | 2 +- 15 files changed, 155 insertions(+), 155 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_lp_event.h delete mode 100644 include/asm-ppc64/iSeries/HvLpEvent.h (limited to 'include') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 330cd783206f..bc5a3689cc05 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -40,7 +40,7 @@ #ifdef CONFIG_PPC64 #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index b1aacf64fb8e..55ecc8d3e73f 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include "irq.h" diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index 96aa0dd72fb0..39ee881c36c3 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 638747c772f8..881d81fcf3b8 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include "setup.h" diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 8e33a90bedb9..7b1a9daae206 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index 5e6046cb414e..504dee836d29 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 5c907b747648..3af1885a8200 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 36f31d202223..da78729413f4 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #define VIOCD_DEVICE "iseries/vcd" diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 33d7820eaab9..694bab3b7bf7 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -46,7 +46,7 @@ #include -#include +#include #include #include #include diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 296797e5a2b5..3242b241d789 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -55,7 +55,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index aaabaf30d4b8..57ba1a11e405 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -77,7 +77,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index c652779c1a32..78397d855d34 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -29,7 +29,7 @@ */ #include -#include +#include #include #include #include diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h new file mode 100644 index 000000000000..75ff1b3ed2e5 --- /dev/null +++ b/include/asm-powerpc/iseries/hv_lp_event.h @@ -0,0 +1,142 @@ +/* + * HvLpEvent.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This file contains the class for HV events in the system. */ + +#ifndef _HVLPEVENT_H +#define _HVLPEVENT_H + +#include +#include +#include +#include + +/* + * HvLpEvent is the structure for Lp Event messages passed between + * partitions through PLIC. + */ + +struct HvEventFlags { + u8 xValid:1; /* Indicates a valid request x00-x00 */ + u8 xRsvd1:4; /* Reserved ... */ + u8 xAckType:1; /* Immediate or deferred ... */ + u8 xAckInd:1; /* Indicates if ACK required ... */ + u8 xFunction:1; /* Interrupt or Acknowledge ... */ +}; + + +struct HvLpEvent { + struct HvEventFlags xFlags; /* Event flags x00-x00 */ + u8 xType; /* Type of message x01-x01 */ + u16 xSubtype; /* Subtype for event x02-x03 */ + u8 xSourceLp; /* Source LP x04-x04 */ + u8 xTargetLp; /* Target LP x05-x05 */ + u8 xSizeMinus1; /* Size of Derived class - 1 x06-x06 */ + u8 xRc; /* RC for Ack flows x07-x07 */ + u16 xSourceInstanceId; /* Source sides instance id x08-x09 */ + u16 xTargetInstanceId; /* Target sides instance id x0A-x0B */ + union { + u32 xSubtypeData; /* Data usable by the subtype x0C-x0F */ + u16 xSubtypeDataShort[2]; /* Data as 2 shorts */ + u8 xSubtypeDataChar[4]; /* Data as 4 chars */ + } x; + + u64 xCorrelationToken; /* Unique value for source/type x10-x17 */ +}; + +typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *); + +/* Register a handler for an event type - returns 0 on success */ +extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType, + LpEventHandler hdlr); + +/* + * Unregister a handler for an event type + * + * This call will sleep until the handler being removed is guaranteed to + * be no longer executing on any CPU. Do not call with locks held. + * + * returns 0 on success + * Unregister will fail if there are any paths open for the type + */ +extern int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType); + +/* + * Open an Lp Event Path for an event type + * returns 0 on success + * openPath will fail if there is no handler registered for the event type. + * The lpIndex specified is the partition index for the target partition + * (for VirtualIo, VirtualLan and SessionMgr) other types specify zero) + */ +extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex); + +/* + * Close an Lp Event Path for a type and partition + * returns 0 on sucess + */ +extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex); + +#define HvLpEvent_Type_Hypervisor 0 +#define HvLpEvent_Type_MachineFac 1 +#define HvLpEvent_Type_SessionMgr 2 +#define HvLpEvent_Type_SpdIo 3 +#define HvLpEvent_Type_VirtualBus 4 +#define HvLpEvent_Type_PciIo 5 +#define HvLpEvent_Type_RioIo 6 +#define HvLpEvent_Type_VirtualLan 7 +#define HvLpEvent_Type_VirtualIo 8 +#define HvLpEvent_Type_NumTypes 9 + +#define HvLpEvent_Rc_Good 0 +#define HvLpEvent_Rc_BufferNotAvailable 1 +#define HvLpEvent_Rc_Cancelled 2 +#define HvLpEvent_Rc_GenericError 3 +#define HvLpEvent_Rc_InvalidAddress 4 +#define HvLpEvent_Rc_InvalidPartition 5 +#define HvLpEvent_Rc_InvalidSize 6 +#define HvLpEvent_Rc_InvalidSubtype 7 +#define HvLpEvent_Rc_InvalidSubtypeData 8 +#define HvLpEvent_Rc_InvalidType 9 +#define HvLpEvent_Rc_PartitionDead 10 +#define HvLpEvent_Rc_PathClosed 11 +#define HvLpEvent_Rc_SubtypeError 12 + +#define HvLpEvent_Function_Ack 0 +#define HvLpEvent_Function_Int 1 + +#define HvLpEvent_AckInd_NoAck 0 +#define HvLpEvent_AckInd_DoAck 1 + +#define HvLpEvent_AckType_ImmediateAck 0 +#define HvLpEvent_AckType_DeferredAck 1 + +#define HvLpDma_Direction_LocalToRemote 0 +#define HvLpDma_Direction_RemoteToLocal 1 + +#define HvLpDma_AddressType_TceIndex 0 +#define HvLpDma_AddressType_RealAddress 1 + +#define HvLpDma_Rc_Good 0 +#define HvLpDma_Rc_Error 1 +#define HvLpDma_Rc_PartitionDead 2 +#define HvLpDma_Rc_PathClosed 3 +#define HvLpDma_Rc_InvalidAddress 4 +#define HvLpDma_Rc_InvalidLength 5 + +#endif /* _HVLPEVENT_H */ diff --git a/include/asm-ppc64/iSeries/HvLpEvent.h b/include/asm-ppc64/iSeries/HvLpEvent.h deleted file mode 100644 index 75ff1b3ed2e5..000000000000 --- a/include/asm-ppc64/iSeries/HvLpEvent.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * HvLpEvent.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This file contains the class for HV events in the system. */ - -#ifndef _HVLPEVENT_H -#define _HVLPEVENT_H - -#include -#include -#include -#include - -/* - * HvLpEvent is the structure for Lp Event messages passed between - * partitions through PLIC. - */ - -struct HvEventFlags { - u8 xValid:1; /* Indicates a valid request x00-x00 */ - u8 xRsvd1:4; /* Reserved ... */ - u8 xAckType:1; /* Immediate or deferred ... */ - u8 xAckInd:1; /* Indicates if ACK required ... */ - u8 xFunction:1; /* Interrupt or Acknowledge ... */ -}; - - -struct HvLpEvent { - struct HvEventFlags xFlags; /* Event flags x00-x00 */ - u8 xType; /* Type of message x01-x01 */ - u16 xSubtype; /* Subtype for event x02-x03 */ - u8 xSourceLp; /* Source LP x04-x04 */ - u8 xTargetLp; /* Target LP x05-x05 */ - u8 xSizeMinus1; /* Size of Derived class - 1 x06-x06 */ - u8 xRc; /* RC for Ack flows x07-x07 */ - u16 xSourceInstanceId; /* Source sides instance id x08-x09 */ - u16 xTargetInstanceId; /* Target sides instance id x0A-x0B */ - union { - u32 xSubtypeData; /* Data usable by the subtype x0C-x0F */ - u16 xSubtypeDataShort[2]; /* Data as 2 shorts */ - u8 xSubtypeDataChar[4]; /* Data as 4 chars */ - } x; - - u64 xCorrelationToken; /* Unique value for source/type x10-x17 */ -}; - -typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *); - -/* Register a handler for an event type - returns 0 on success */ -extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType, - LpEventHandler hdlr); - -/* - * Unregister a handler for an event type - * - * This call will sleep until the handler being removed is guaranteed to - * be no longer executing on any CPU. Do not call with locks held. - * - * returns 0 on success - * Unregister will fail if there are any paths open for the type - */ -extern int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType); - -/* - * Open an Lp Event Path for an event type - * returns 0 on success - * openPath will fail if there is no handler registered for the event type. - * The lpIndex specified is the partition index for the target partition - * (for VirtualIo, VirtualLan and SessionMgr) other types specify zero) - */ -extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex); - -/* - * Close an Lp Event Path for a type and partition - * returns 0 on sucess - */ -extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex); - -#define HvLpEvent_Type_Hypervisor 0 -#define HvLpEvent_Type_MachineFac 1 -#define HvLpEvent_Type_SessionMgr 2 -#define HvLpEvent_Type_SpdIo 3 -#define HvLpEvent_Type_VirtualBus 4 -#define HvLpEvent_Type_PciIo 5 -#define HvLpEvent_Type_RioIo 6 -#define HvLpEvent_Type_VirtualLan 7 -#define HvLpEvent_Type_VirtualIo 8 -#define HvLpEvent_Type_NumTypes 9 - -#define HvLpEvent_Rc_Good 0 -#define HvLpEvent_Rc_BufferNotAvailable 1 -#define HvLpEvent_Rc_Cancelled 2 -#define HvLpEvent_Rc_GenericError 3 -#define HvLpEvent_Rc_InvalidAddress 4 -#define HvLpEvent_Rc_InvalidPartition 5 -#define HvLpEvent_Rc_InvalidSize 6 -#define HvLpEvent_Rc_InvalidSubtype 7 -#define HvLpEvent_Rc_InvalidSubtypeData 8 -#define HvLpEvent_Rc_InvalidType 9 -#define HvLpEvent_Rc_PartitionDead 10 -#define HvLpEvent_Rc_PathClosed 11 -#define HvLpEvent_Rc_SubtypeError 12 - -#define HvLpEvent_Function_Ack 0 -#define HvLpEvent_Function_Int 1 - -#define HvLpEvent_AckInd_NoAck 0 -#define HvLpEvent_AckInd_DoAck 1 - -#define HvLpEvent_AckType_ImmediateAck 0 -#define HvLpEvent_AckType_DeferredAck 1 - -#define HvLpDma_Direction_LocalToRemote 0 -#define HvLpDma_Direction_RemoteToLocal 1 - -#define HvLpDma_AddressType_TceIndex 0 -#define HvLpDma_AddressType_RealAddress 1 - -#define HvLpDma_Rc_Good 0 -#define HvLpDma_Rc_Error 1 -#define HvLpDma_Rc_PartitionDead 2 -#define HvLpDma_Rc_PathClosed 3 -#define HvLpDma_Rc_InvalidAddress 4 -#define HvLpDma_Rc_InvalidLength 5 - -#endif /* _HVLPEVENT_H */ diff --git a/include/asm-ppc64/iSeries/vio.h b/include/asm-ppc64/iSeries/vio.h index 6c05e6257f53..4d39ce6c687a 100644 --- a/include/asm-ppc64/iSeries/vio.h +++ b/include/asm-ppc64/iSeries/vio.h @@ -42,7 +42,7 @@ #define _ISERIES_VIO_H #include -#include +#include /* * iSeries virtual I/O events use the subtype field in -- cgit v1.2.3 From 1ec65d76f3e5d4863b4bf93dfd2bff37f8bf4374 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 13:46:07 +1100 Subject: merge filename and modify references to iseries/hv_types.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/call_hpt.h | 2 +- arch/powerpc/platforms/iseries/call_pci.h | 2 +- arch/powerpc/platforms/iseries/call_sm.h | 2 +- arch/powerpc/platforms/iseries/hvlog.c | 2 +- arch/powerpc/platforms/iseries/irq.c | 2 +- arch/powerpc/platforms/iseries/vio.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 2 +- arch/powerpc/platforms/iseries/vpdinfo.c | 2 +- drivers/block/viodasd.c | 2 +- drivers/cdrom/viocd.c | 2 +- drivers/net/iseries_veth.c | 2 +- drivers/scsi/ibmvscsi/iseries_vscsi.c | 2 +- include/asm-powerpc/iseries/hv_call.h | 2 +- include/asm-powerpc/iseries/hv_call_event.h | 2 +- include/asm-powerpc/iseries/hv_call_xm.h | 2 +- include/asm-powerpc/iseries/hv_lp_config.h | 2 +- include/asm-powerpc/iseries/hv_lp_event.h | 2 +- include/asm-powerpc/iseries/hv_types.h | 113 ++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/HvTypes.h | 113 ---------------------------- include/asm-ppc64/iSeries/mf.h | 2 +- include/asm-ppc64/iSeries/vio.h | 2 +- 21 files changed, 132 insertions(+), 132 deletions(-) create mode 100644 include/asm-powerpc/iseries/hv_types.h delete mode 100644 include/asm-ppc64/iSeries/HvTypes.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h index a626d8c289ee..a843b0f87b72 100644 --- a/arch/powerpc/platforms/iseries/call_hpt.h +++ b/arch/powerpc/platforms/iseries/call_hpt.h @@ -24,7 +24,7 @@ */ #include -#include +#include #include #define HvCallHptGetHptAddress HvCallHpt + 0 diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h index 53cc163d4689..59d4e0ad5cf3 100644 --- a/arch/powerpc/platforms/iseries/call_pci.h +++ b/arch/powerpc/platforms/iseries/call_pci.h @@ -26,7 +26,7 @@ #define _PLATFORMS_ISERIES_CALL_PCI_H #include -#include +#include /* * DSA == Direct Select Address diff --git a/arch/powerpc/platforms/iseries/call_sm.h b/arch/powerpc/platforms/iseries/call_sm.h index a9726822e953..c7e251619f48 100644 --- a/arch/powerpc/platforms/iseries/call_sm.h +++ b/arch/powerpc/platforms/iseries/call_sm.h @@ -24,7 +24,7 @@ */ #include -#include +#include #define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c index 48a3f7900389..62ec73479687 100644 --- a/arch/powerpc/platforms/iseries/hvlog.c +++ b/arch/powerpc/platforms/iseries/hvlog.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include void HvCall_writeLogBuffer(const void *buffer, u64 len) diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 55ecc8d3e73f..c1135912cc05 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index 4e2dafc83bb2..d607ebaef270 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 7b1a9daae206..17bf4e70d5cc 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c index 9c318849dee7..23a6d1e5b429 100644 --- a/arch/powerpc/platforms/iseries/vpdinfo.c +++ b/arch/powerpc/platforms/iseries/vpdinfo.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include "pci.h" #include "call_pci.h" diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 3af1885a8200..436f169baf02 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -45,7 +45,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index da78729413f4..cb87d270b6bb 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -46,7 +46,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 57ba1a11e405..1070140d9f59 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -76,7 +76,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index 78397d855d34..ed89659ac3bf 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/asm-powerpc/iseries/hv_call.h b/include/asm-powerpc/iseries/hv_call.h index 5edfe2c8ea33..af59cc1e9691 100644 --- a/include/asm-powerpc/iseries/hv_call.h +++ b/include/asm-powerpc/iseries/hv_call.h @@ -24,7 +24,7 @@ #define _HVCALL_H #include -#include +#include #include /* Type of yield for HvCallBaseYieldProcessor */ diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h index 202c87c39ef4..c2770b056ae8 100644 --- a/include/asm-powerpc/iseries/hv_call_event.h +++ b/include/asm-powerpc/iseries/hv_call_event.h @@ -24,7 +24,7 @@ #define _HVCALLEVENT_H #include -#include +#include #include struct HvLpEvent; diff --git a/include/asm-powerpc/iseries/hv_call_xm.h b/include/asm-powerpc/iseries/hv_call_xm.h index 8a7b6e3c01ac..fd36b11612f8 100644 --- a/include/asm-powerpc/iseries/hv_call_xm.h +++ b/include/asm-powerpc/iseries/hv_call_xm.h @@ -6,7 +6,7 @@ #define _HVCALLXM_H #include -#include +#include #define HvCallXmGetTceTableParms HvCallXm + 0 #define HvCallXmTestBus HvCallXm + 1 diff --git a/include/asm-powerpc/iseries/hv_lp_config.h b/include/asm-powerpc/iseries/hv_lp_config.h index 9077fc8e3f6c..600795bbc890 100644 --- a/include/asm-powerpc/iseries/hv_lp_config.h +++ b/include/asm-powerpc/iseries/hv_lp_config.h @@ -25,7 +25,7 @@ */ #include -#include +#include #include enum { diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h index 75ff1b3ed2e5..2a3b773854b1 100644 --- a/include/asm-powerpc/iseries/hv_lp_event.h +++ b/include/asm-powerpc/iseries/hv_lp_event.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include /* diff --git a/include/asm-powerpc/iseries/hv_types.h b/include/asm-powerpc/iseries/hv_types.h new file mode 100644 index 000000000000..b1ef2b4cb3e3 --- /dev/null +++ b/include/asm-powerpc/iseries/hv_types.h @@ -0,0 +1,113 @@ +/* + * HvTypes.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVTYPES_H +#define _HVTYPES_H + +/* + * General typedefs for the hypervisor. + */ + +#include + +typedef u8 HvLpIndex; +typedef u16 HvLpInstanceId; +typedef u64 HvLpTOD; +typedef u64 HvLpSystemSerialNum; +typedef u8 HvLpDeviceSerialNum[12]; +typedef u16 HvLpSanHwSet; +typedef u16 HvLpBus; +typedef u16 HvLpBoard; +typedef u16 HvLpCard; +typedef u8 HvLpDeviceType[4]; +typedef u8 HvLpDeviceModel[3]; +typedef u64 HvIoToken; +typedef u8 HvLpName[8]; +typedef u32 HvIoId; +typedef u64 HvRealMemoryIndex; +typedef u32 HvLpIndexMap; /* Must hold HVMAXARCHITECTEDLPS bits!!! */ +typedef u16 HvLpVrmIndex; +typedef u32 HvXmGenerationId; +typedef u8 HvLpBusPool; +typedef u8 HvLpSharedPoolIndex; +typedef u16 HvLpSharedProcUnitsX100; +typedef u8 HvLpVirtualLanIndex; +typedef u16 HvLpVirtualLanIndexMap; /* Must hold HVMAXARCHITECTEDVIRTUALLANS bits!!! */ +typedef u16 HvBusNumber; /* Hypervisor Bus Number */ +typedef u8 HvSubBusNumber; /* Hypervisor SubBus Number */ +typedef u8 HvAgentId; /* Hypervisor DevFn */ + + +#define HVMAXARCHITECTEDLPS 32 +#define HVMAXARCHITECTEDVIRTUALLANS 16 +#define HVMAXARCHITECTEDVIRTUALDISKS 32 +#define HVMAXARCHITECTEDVIRTUALCDROMS 8 +#define HVMAXARCHITECTEDVIRTUALTAPES 8 +#define HVCHUNKSIZE (256 * 1024) +#define HVPAGESIZE (4 * 1024) +#define HVLPMINMEGSPRIMARY 256 +#define HVLPMINMEGSSECONDARY 64 +#define HVCHUNKSPERMEG 4 +#define HVPAGESPERMEG 256 +#define HVPAGESPERCHUNK 64 + +#define HvLpIndexInvalid ((HvLpIndex)0xff) + +/* + * Enums for the sub-components under PLIC + * Used in HvCall and HvPrimaryCall + */ +enum { + HvCallCompId = 0, + HvCallCpuCtlsCompId = 1, + HvCallCfgCompId = 2, + HvCallEventCompId = 3, + HvCallHptCompId = 4, + HvCallPciCompId = 5, + HvCallSlmCompId = 6, + HvCallSmCompId = 7, + HvCallSpdCompId = 8, + HvCallXmCompId = 9, + HvCallRioCompId = 10, + HvCallRsvd3CompId = 11, + HvCallRsvd2CompId = 12, + HvCallRsvd1CompId = 13, + HvCallMaxCompId = 14, + HvPrimaryCallCompId = 0, + HvPrimaryCallCfgCompId = 1, + HvPrimaryCallPciCompId = 2, + HvPrimaryCallSmCompId = 3, + HvPrimaryCallSpdCompId = 4, + HvPrimaryCallXmCompId = 5, + HvPrimaryCallRioCompId = 6, + HvPrimaryCallRsvd7CompId = 7, + HvPrimaryCallRsvd6CompId = 8, + HvPrimaryCallRsvd5CompId = 9, + HvPrimaryCallRsvd4CompId = 10, + HvPrimaryCallRsvd3CompId = 11, + HvPrimaryCallRsvd2CompId = 12, + HvPrimaryCallRsvd1CompId = 13, + HvPrimaryCallMaxCompId = HvCallMaxCompId +}; + +struct HvLpBufferList { + u64 addr; + u64 len; +}; + +#endif /* _HVTYPES_H */ diff --git a/include/asm-ppc64/iSeries/HvTypes.h b/include/asm-ppc64/iSeries/HvTypes.h deleted file mode 100644 index b1ef2b4cb3e3..000000000000 --- a/include/asm-ppc64/iSeries/HvTypes.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * HvTypes.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _HVTYPES_H -#define _HVTYPES_H - -/* - * General typedefs for the hypervisor. - */ - -#include - -typedef u8 HvLpIndex; -typedef u16 HvLpInstanceId; -typedef u64 HvLpTOD; -typedef u64 HvLpSystemSerialNum; -typedef u8 HvLpDeviceSerialNum[12]; -typedef u16 HvLpSanHwSet; -typedef u16 HvLpBus; -typedef u16 HvLpBoard; -typedef u16 HvLpCard; -typedef u8 HvLpDeviceType[4]; -typedef u8 HvLpDeviceModel[3]; -typedef u64 HvIoToken; -typedef u8 HvLpName[8]; -typedef u32 HvIoId; -typedef u64 HvRealMemoryIndex; -typedef u32 HvLpIndexMap; /* Must hold HVMAXARCHITECTEDLPS bits!!! */ -typedef u16 HvLpVrmIndex; -typedef u32 HvXmGenerationId; -typedef u8 HvLpBusPool; -typedef u8 HvLpSharedPoolIndex; -typedef u16 HvLpSharedProcUnitsX100; -typedef u8 HvLpVirtualLanIndex; -typedef u16 HvLpVirtualLanIndexMap; /* Must hold HVMAXARCHITECTEDVIRTUALLANS bits!!! */ -typedef u16 HvBusNumber; /* Hypervisor Bus Number */ -typedef u8 HvSubBusNumber; /* Hypervisor SubBus Number */ -typedef u8 HvAgentId; /* Hypervisor DevFn */ - - -#define HVMAXARCHITECTEDLPS 32 -#define HVMAXARCHITECTEDVIRTUALLANS 16 -#define HVMAXARCHITECTEDVIRTUALDISKS 32 -#define HVMAXARCHITECTEDVIRTUALCDROMS 8 -#define HVMAXARCHITECTEDVIRTUALTAPES 8 -#define HVCHUNKSIZE (256 * 1024) -#define HVPAGESIZE (4 * 1024) -#define HVLPMINMEGSPRIMARY 256 -#define HVLPMINMEGSSECONDARY 64 -#define HVCHUNKSPERMEG 4 -#define HVPAGESPERMEG 256 -#define HVPAGESPERCHUNK 64 - -#define HvLpIndexInvalid ((HvLpIndex)0xff) - -/* - * Enums for the sub-components under PLIC - * Used in HvCall and HvPrimaryCall - */ -enum { - HvCallCompId = 0, - HvCallCpuCtlsCompId = 1, - HvCallCfgCompId = 2, - HvCallEventCompId = 3, - HvCallHptCompId = 4, - HvCallPciCompId = 5, - HvCallSlmCompId = 6, - HvCallSmCompId = 7, - HvCallSpdCompId = 8, - HvCallXmCompId = 9, - HvCallRioCompId = 10, - HvCallRsvd3CompId = 11, - HvCallRsvd2CompId = 12, - HvCallRsvd1CompId = 13, - HvCallMaxCompId = 14, - HvPrimaryCallCompId = 0, - HvPrimaryCallCfgCompId = 1, - HvPrimaryCallPciCompId = 2, - HvPrimaryCallSmCompId = 3, - HvPrimaryCallSpdCompId = 4, - HvPrimaryCallXmCompId = 5, - HvPrimaryCallRioCompId = 6, - HvPrimaryCallRsvd7CompId = 7, - HvPrimaryCallRsvd6CompId = 8, - HvPrimaryCallRsvd5CompId = 9, - HvPrimaryCallRsvd4CompId = 10, - HvPrimaryCallRsvd3CompId = 11, - HvPrimaryCallRsvd2CompId = 12, - HvPrimaryCallRsvd1CompId = 13, - HvPrimaryCallMaxCompId = HvCallMaxCompId -}; - -struct HvLpBufferList { - u64 addr; - u64 len; -}; - -#endif /* _HVTYPES_H */ diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h index f84404a07f4b..166cd73f5c15 100644 --- a/include/asm-ppc64/iSeries/mf.h +++ b/include/asm-ppc64/iSeries/mf.h @@ -28,7 +28,7 @@ #include -#include +#include #include struct rtc_time; diff --git a/include/asm-ppc64/iSeries/vio.h b/include/asm-ppc64/iSeries/vio.h index 4d39ce6c687a..2b57dbf5c257 100644 --- a/include/asm-ppc64/iSeries/vio.h +++ b/include/asm-ppc64/iSeries/vio.h @@ -41,7 +41,7 @@ #ifndef _ISERIES_VIO_H #define _ISERIES_VIO_H -#include +#include #include /* -- cgit v1.2.3 From 7b487bb801b4bd790aa4bf7c157889f9d05e239c Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 13:48:25 +1100 Subject: merge filename and modify references to iseries/it_exp_vpd_panel.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/lpardata.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 2 +- arch/ppc64/kernel/lparcfg.c | 2 +- include/asm-powerpc/iseries/it_exp_vpd_panel.h | 52 ++++++++++++++++++++++++++ include/asm-ppc64/iSeries/ItExtVpdPanel.h | 52 -------------------------- 5 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 include/asm-powerpc/iseries/it_exp_vpd_panel.h delete mode 100644 include/asm-ppc64/iSeries/ItExtVpdPanel.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index ed2ffee6f731..9c8c21252142 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include "vpd_areas.h" diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 17bf4e70d5cc..6fa39ae5f12c 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index e4236f2707e1..e86155770bbc 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #define MODULE_VERS "1.6" diff --git a/include/asm-powerpc/iseries/it_exp_vpd_panel.h b/include/asm-powerpc/iseries/it_exp_vpd_panel.h new file mode 100644 index 000000000000..4c546a8802b4 --- /dev/null +++ b/include/asm-powerpc/iseries/it_exp_vpd_panel.h @@ -0,0 +1,52 @@ +/* + * ItExtVpdPanel.h + * Copyright (C) 2002 Dave Boutcher IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITEXTVPDPANEL_H +#define _ITEXTVPDPANEL_H + +/* + * This struct maps the panel information + * + * Warning: + * This data must match the architecture for the panel information + */ + +#include + +struct ItExtVpdPanel { + /* Definition of the Extended Vpd On Panel Data Area */ + char systemSerial[8]; + char mfgID[4]; + char reserved1[24]; + char machineType[4]; + char systemID[6]; + char somUniqueCnt[4]; + char serialNumberCount; + char reserved2[7]; + u16 bbu3; + u16 bbu2; + u16 bbu1; + char xLocationLabel[8]; + u8 xRsvd1[6]; + u16 xFrameId; + u8 xRsvd2[48]; +}; + +extern struct ItExtVpdPanel xItExtVpdPanel; + +#endif /* _ITEXTVPDPANEL_H */ diff --git a/include/asm-ppc64/iSeries/ItExtVpdPanel.h b/include/asm-ppc64/iSeries/ItExtVpdPanel.h deleted file mode 100644 index 4c546a8802b4..000000000000 --- a/include/asm-ppc64/iSeries/ItExtVpdPanel.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * ItExtVpdPanel.h - * Copyright (C) 2002 Dave Boutcher IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _ITEXTVPDPANEL_H -#define _ITEXTVPDPANEL_H - -/* - * This struct maps the panel information - * - * Warning: - * This data must match the architecture for the panel information - */ - -#include - -struct ItExtVpdPanel { - /* Definition of the Extended Vpd On Panel Data Area */ - char systemSerial[8]; - char mfgID[4]; - char reserved1[24]; - char machineType[4]; - char systemID[6]; - char somUniqueCnt[4]; - char serialNumberCount; - char reserved2[7]; - u16 bbu3; - u16 bbu2; - u16 bbu1; - char xLocationLabel[8]; - u8 xRsvd1[6]; - u16 xFrameId; - u8 xRsvd2[48]; -}; - -extern struct ItExtVpdPanel xItExtVpdPanel; - -#endif /* _ITEXTVPDPANEL_H */ -- cgit v1.2.3 From f218aab5cf74672a368933965f5bb612dac3c349 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 13:51:41 +1100 Subject: merge filename and modify references to iseries/it_lp_naca.h Signed-off-by: Kelly Daly --- arch/powerpc/kernel/setup_64.c | 2 +- arch/powerpc/platforms/iseries/lpardata.c | 2 +- arch/powerpc/platforms/iseries/lpevents.c | 2 +- include/asm-powerpc/iseries/hv_lp_config.h | 2 +- include/asm-powerpc/iseries/it_lp_naca.h | 80 ++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/ItLpNaca.h | 80 ------------------------------ 6 files changed, 84 insertions(+), 84 deletions(-) create mode 100644 include/asm-powerpc/iseries/it_lp_naca.h delete mode 100644 include/asm-ppc64/iSeries/ItLpNaca.h (limited to 'include') diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 40c48100bf1b..079867e18145 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index 9c8c21252142..d0937613e776 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index 39ee881c36c3..f0040d469a49 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include /* * The LpQueue is used to pass event data from the hypervisor to diff --git a/include/asm-powerpc/iseries/hv_lp_config.h b/include/asm-powerpc/iseries/hv_lp_config.h index 600795bbc890..db577f079f25 100644 --- a/include/asm-powerpc/iseries/hv_lp_config.h +++ b/include/asm-powerpc/iseries/hv_lp_config.h @@ -26,7 +26,7 @@ #include #include -#include +#include enum { HvCallCfg_Cur = 0, diff --git a/include/asm-powerpc/iseries/it_lp_naca.h b/include/asm-powerpc/iseries/it_lp_naca.h new file mode 100644 index 000000000000..225d0176779d --- /dev/null +++ b/include/asm-powerpc/iseries/it_lp_naca.h @@ -0,0 +1,80 @@ +/* + * ItLpNaca.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITLPNACA_H +#define _ITLPNACA_H + +#include + +/* + * This control block contains the data that is shared between the + * hypervisor (PLIC) and the OS. + */ + +struct ItLpNaca { +// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data + u32 xDesc; // Eye catcher x00-x03 + u16 xSize; // Size of this class x04-x05 + u16 xIntHdlrOffset; // Offset to IntHdlr array x06-x07 + u8 xMaxIntHdlrEntries; // Number of entries in array x08-x08 + u8 xPrimaryLpIndex; // LP Index of Primary x09-x09 + u8 xServiceLpIndex; // LP Ind of Service Focal Pointx0A-x0A + u8 xLpIndex; // LP Index x0B-x0B + u16 xMaxLpQueues; // Number of allocated queues x0C-x0D + u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F + u8 xPirEnvironMode:8; // Piranha or hardware x10-x10 + u8 xPirConsoleMode:8; // Piranha console indicator x11-x11 + u8 xPirDasdMode:8; // Piranha dasd indicator x12-x12 + u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17 + u8 xLparInstalled:1; // Is LPAR installed on system x18-x1F + u8 xSysPartitioned:1; // Is the system partitioned ... + u8 xHwSyncedTBs:1; // Hardware synced TBs ... + u8 xIntProcUtilHmt:1; // Utilize HMT for interrupts ... + u8 xRsvd1_1:4; // Reserved ... + u8 xSpVpdFormat:8; // VPD areas are in CSP format ... + u8 xIntProcRatio:8; // Ratio of int procs to procs ... + u8 xRsvd1_2[5]; // Reserved ... + u16 xRsvd1_3; // Reserved x20-x21 + u16 xPlicVrmIndex; // VRM index of PLIC x22-x23 + u16 xMinSupportedSlicVrmInd;// Min supported OS VRM index x24-x25 + u16 xMinCompatableSlicVrmInd;// Min compatible OS VRM index x26-x27 + u64 xLoadAreaAddr; // ER address of load area x28-x2F + u32 xLoadAreaChunks; // Chunks for the load area x30-x33 + u32 xPaseSysCallCRMask; // Mask used to test CR before x34-x37 + // doing an ASR switch on PASE + // system call. + u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f + u8 xRsvd1_4[64]; // x40-x7F + +// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data + u8 xRsvd2_0[128]; // Reserved x00-x7F + +// CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators +// NB: Padding required to keep xInterrruptHdlr at x300 which is required +// for v4r4 PLIC. + u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F + u8 xRsvd3_0[384]; // Reserved 180-2FF + +// CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt +// handlers + u64 xInterruptHdlr[32]; // Interrupt handlers 300-x3FF +}; + +extern struct ItLpNaca itLpNaca; + +#endif /* _ITLPNACA_H */ diff --git a/include/asm-ppc64/iSeries/ItLpNaca.h b/include/asm-ppc64/iSeries/ItLpNaca.h deleted file mode 100644 index 225d0176779d..000000000000 --- a/include/asm-ppc64/iSeries/ItLpNaca.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * ItLpNaca.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _ITLPNACA_H -#define _ITLPNACA_H - -#include - -/* - * This control block contains the data that is shared between the - * hypervisor (PLIC) and the OS. - */ - -struct ItLpNaca { -// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data - u32 xDesc; // Eye catcher x00-x03 - u16 xSize; // Size of this class x04-x05 - u16 xIntHdlrOffset; // Offset to IntHdlr array x06-x07 - u8 xMaxIntHdlrEntries; // Number of entries in array x08-x08 - u8 xPrimaryLpIndex; // LP Index of Primary x09-x09 - u8 xServiceLpIndex; // LP Ind of Service Focal Pointx0A-x0A - u8 xLpIndex; // LP Index x0B-x0B - u16 xMaxLpQueues; // Number of allocated queues x0C-x0D - u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F - u8 xPirEnvironMode:8; // Piranha or hardware x10-x10 - u8 xPirConsoleMode:8; // Piranha console indicator x11-x11 - u8 xPirDasdMode:8; // Piranha dasd indicator x12-x12 - u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17 - u8 xLparInstalled:1; // Is LPAR installed on system x18-x1F - u8 xSysPartitioned:1; // Is the system partitioned ... - u8 xHwSyncedTBs:1; // Hardware synced TBs ... - u8 xIntProcUtilHmt:1; // Utilize HMT for interrupts ... - u8 xRsvd1_1:4; // Reserved ... - u8 xSpVpdFormat:8; // VPD areas are in CSP format ... - u8 xIntProcRatio:8; // Ratio of int procs to procs ... - u8 xRsvd1_2[5]; // Reserved ... - u16 xRsvd1_3; // Reserved x20-x21 - u16 xPlicVrmIndex; // VRM index of PLIC x22-x23 - u16 xMinSupportedSlicVrmInd;// Min supported OS VRM index x24-x25 - u16 xMinCompatableSlicVrmInd;// Min compatible OS VRM index x26-x27 - u64 xLoadAreaAddr; // ER address of load area x28-x2F - u32 xLoadAreaChunks; // Chunks for the load area x30-x33 - u32 xPaseSysCallCRMask; // Mask used to test CR before x34-x37 - // doing an ASR switch on PASE - // system call. - u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f - u8 xRsvd1_4[64]; // x40-x7F - -// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data - u8 xRsvd2_0[128]; // Reserved x00-x7F - -// CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators -// NB: Padding required to keep xInterrruptHdlr at x300 which is required -// for v4r4 PLIC. - u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F - u8 xRsvd3_0[384]; // Reserved 180-2FF - -// CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt -// handlers - u64 xInterruptHdlr[32]; // Interrupt handlers 300-x3FF -}; - -extern struct ItLpNaca itLpNaca; - -#endif /* _ITLPNACA_H */ -- cgit v1.2.3 From 8875ccfb7a6bd69d95a4e889ab36adda06c30d9e Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 14:13:34 +1100 Subject: merge filename and modify references to iseries/it_lp_queue.h Signed-off-by: Kelly Daly --- arch/powerpc/kernel/time.c | 2 +- arch/powerpc/platforms/iseries/lpardata.c | 2 +- arch/powerpc/platforms/iseries/lpevents.c | 2 +- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/proc.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/ppc64/kernel/irq.c | 2 +- arch/ppc64/kernel/pacaData.c | 2 +- include/asm-powerpc/iseries/it_lp_queue.h | 81 +++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/ItLpQueue.h | 81 ------------------------------- 10 files changed, 89 insertions(+), 89 deletions(-) create mode 100644 include/asm-powerpc/iseries/it_lp_queue.h delete mode 100644 include/asm-ppc64/iSeries/ItLpQueue.h (limited to 'include') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 348746c55ebd..6996a593dcb3 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -66,7 +66,7 @@ #include #endif #ifdef CONFIG_PPC_ISERIES -#include +#include #include #endif diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index d0937613e776..dfe38eb4036d 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "vpd_areas.h" #include "spcomm_area.h" diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index f0040d469a49..e9fb98bf895f 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 027df204446d..689f65a49c00 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include "setup.h" diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c index beba0f62e653..e68b6b5fa89f 100644 --- a/arch/powerpc/platforms/iseries/proc.c +++ b/arch/powerpc/platforms/iseries/proc.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include "processor_vpd.h" diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 881d81fcf3b8..9a9e54b736d3 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index f41afe545045..310931dbd4ae 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 33a2d8db3f21..5e27e5a6a35d 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include static union { diff --git a/include/asm-powerpc/iseries/it_lp_queue.h b/include/asm-powerpc/iseries/it_lp_queue.h new file mode 100644 index 000000000000..69b26ad74135 --- /dev/null +++ b/include/asm-powerpc/iseries/it_lp_queue.h @@ -0,0 +1,81 @@ +/* + * ItLpQueue.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITLPQUEUE_H +#define _ITLPQUEUE_H + +/* + * This control block defines the simple LP queue structure that is + * shared between the hypervisor (PLIC) and the OS in order to send + * events to an LP. + */ + +#include +#include + +struct HvLpEvent; + +#define ITMaxLpQueues 8 + +#define NotUsed 0 // Queue will not be used by PLIC +#define DedicatedIo 1 // Queue dedicated to IO processor specified +#define DedicatedLp 2 // Queue dedicated to LP specified +#define Shared 3 // Queue shared for both IO and LP + +#define LpEventStackSize 4096 +#define LpEventMaxSize 256 +#define LpEventAlign 64 + +struct hvlpevent_queue { +/* + * The xSlicCurEventPtr is the pointer to the next event stack entry + * that will become valid. The OS must peek at this entry to determine + * if it is valid. PLIC will set the valid indicator as the very last + * store into that entry. + * + * When the OS has completed processing of the event then it will mark + * the event as invalid so that PLIC knows it can store into that event + * location again. + * + * If the event stack fills and there are overflow events, then PLIC + * will set the xPlicOverflowIntPending flag in which case the OS will + * have to fetch the additional LP events once they have drained the + * event stack. + * + * The first 16-bytes are known by both the OS and PLIC. The remainder + * of the cache line is for use by the OS. + */ + u8 xPlicOverflowIntPending;// 0x00 Overflow events are pending + u8 xPlicStatus; // 0x01 DedicatedIo or DedicatedLp or NotUsed + u16 xSlicLogicalProcIndex; // 0x02 Logical Proc Index for correlation + u8 xPlicRsvd[12]; // 0x04 + char *xSlicCurEventPtr; // 0x10 + char *xSlicLastValidEventPtr; // 0x18 + char *xSlicEventStackPtr; // 0x20 + u8 xIndex; // 0x28 unique sequential index. + u8 xSlicRsvd[3]; // 0x29-2b + spinlock_t lock; +}; + +extern struct hvlpevent_queue hvlpevent_queue; + +extern int hvlpevent_is_pending(void); +extern void process_hvlpevents(struct pt_regs *); +extern void setup_hvlpevent_queue(void); + +#endif /* _ITLPQUEUE_H */ diff --git a/include/asm-ppc64/iSeries/ItLpQueue.h b/include/asm-ppc64/iSeries/ItLpQueue.h deleted file mode 100644 index 69b26ad74135..000000000000 --- a/include/asm-ppc64/iSeries/ItLpQueue.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ItLpQueue.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _ITLPQUEUE_H -#define _ITLPQUEUE_H - -/* - * This control block defines the simple LP queue structure that is - * shared between the hypervisor (PLIC) and the OS in order to send - * events to an LP. - */ - -#include -#include - -struct HvLpEvent; - -#define ITMaxLpQueues 8 - -#define NotUsed 0 // Queue will not be used by PLIC -#define DedicatedIo 1 // Queue dedicated to IO processor specified -#define DedicatedLp 2 // Queue dedicated to LP specified -#define Shared 3 // Queue shared for both IO and LP - -#define LpEventStackSize 4096 -#define LpEventMaxSize 256 -#define LpEventAlign 64 - -struct hvlpevent_queue { -/* - * The xSlicCurEventPtr is the pointer to the next event stack entry - * that will become valid. The OS must peek at this entry to determine - * if it is valid. PLIC will set the valid indicator as the very last - * store into that entry. - * - * When the OS has completed processing of the event then it will mark - * the event as invalid so that PLIC knows it can store into that event - * location again. - * - * If the event stack fills and there are overflow events, then PLIC - * will set the xPlicOverflowIntPending flag in which case the OS will - * have to fetch the additional LP events once they have drained the - * event stack. - * - * The first 16-bytes are known by both the OS and PLIC. The remainder - * of the cache line is for use by the OS. - */ - u8 xPlicOverflowIntPending;// 0x00 Overflow events are pending - u8 xPlicStatus; // 0x01 DedicatedIo or DedicatedLp or NotUsed - u16 xSlicLogicalProcIndex; // 0x02 Logical Proc Index for correlation - u8 xPlicRsvd[12]; // 0x04 - char *xSlicCurEventPtr; // 0x10 - char *xSlicLastValidEventPtr; // 0x18 - char *xSlicEventStackPtr; // 0x20 - u8 xIndex; // 0x28 unique sequential index. - u8 xSlicRsvd[3]; // 0x29-2b - spinlock_t lock; -}; - -extern struct hvlpevent_queue hvlpevent_queue; - -extern int hvlpevent_is_pending(void); -extern void process_hvlpevents(struct pt_regs *); -extern void setup_hvlpevent_queue(void); - -#endif /* _ITLPQUEUE_H */ -- cgit v1.2.3 From 847aeb6bad0876ff9c250725e905a41c6050157c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 2 Nov 2005 11:44:26 +1100 Subject: [PATCH] powerpc: Fix merged ipcbuf.h Oops, when merging ipcbuf.h, I forgot that 'u64' can't be used in user-visible headers. This patch corrects the problem, replacing the unused fields with an array of four __u32s. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/ipcbuf.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/ipcbuf.h b/include/asm-powerpc/ipcbuf.h index dc0f4d16d05e..71382c1ec6e3 100644 --- a/include/asm-powerpc/ipcbuf.h +++ b/include/asm-powerpc/ipcbuf.h @@ -27,8 +27,7 @@ struct ipc64_perm __kernel_mode_t mode; unsigned int seq; unsigned int __pad1; - u64 __unused1; - u64 __unused2; + __u32 __unused[4]; }; #endif /* _ASM_POWERPC_IPCBUF_H */ -- cgit v1.2.3 From 2ff2ae7a0d7bfd813325663dc6353d034db7473d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 2 Nov 2005 13:58:22 +1100 Subject: [PATCH] powerpc: Merge futex.h This patch merges the ppc32 and ppc64 versions of futex.h, essentially by taking the ppc64 version as the powerpc version. The old ppc32 version did not implement the futex_atomic_op_inuser() callback (it always returned -ENOSYS), so FUTEX_WAKE_OP would not work on ppc32. In fact the ppc64 version of this function is almost suitable for ppc32 as well - the only change needed is to extend ppc_asm.h with a macro expanding to to the right pseudo-op to store a pointer (either ".long" or ".llong"). Built and booted on pSeries. Built for 32-bit powermac. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/futex.h | 84 +++++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/ppc_asm.h | 7 ++++ include/asm-ppc/futex.h | 53 --------------------------- include/asm-ppc64/futex.h | 83 ------------------------------------------ 4 files changed, 91 insertions(+), 136 deletions(-) create mode 100644 include/asm-powerpc/futex.h delete mode 100644 include/asm-ppc/futex.h delete mode 100644 include/asm-ppc64/futex.h (limited to 'include') diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h new file mode 100644 index 000000000000..37c94e52ab6d --- /dev/null +++ b/include/asm-powerpc/futex.h @@ -0,0 +1,84 @@ +#ifndef _ASM_POWERPC_FUTEX_H +#define _ASM_POWERPC_FUTEX_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile ( \ + SYNC_ON_SMP \ +"1: lwarx %0,0,%2\n" \ + insn \ +"2: stwcx. %1,0,%2\n" \ + "bne- 1b\n" \ + "li %1,0\n" \ +"3: .section .fixup,\"ax\"\n" \ +"4: li %1,%3\n" \ + "b 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + ".align 3\n" \ + DATAL " 1b,4b,2b,4b\n" \ + ".previous" \ + : "=&r" (oldval), "=&r" (ret) \ + : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ + : "cr0", "memory") + +static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + inc_preempt_count(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + dec_preempt_count(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; + } + } + return ret; +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_FUTEX_H */ diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index f99f2af82ca5..c534ca41224b 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -506,6 +506,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #else #define __ASM_CONST(x) x##UL #define ASM_CONST(x) __ASM_CONST(x) + +#ifdef CONFIG_PPC64 +#define DATAL ".llong" +#else +#define DATAL ".long" +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_PPC_ASM_H */ diff --git a/include/asm-ppc/futex.h b/include/asm-ppc/futex.h deleted file mode 100644 index 9feff4ce1424..000000000000 --- a/include/asm-ppc/futex.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#ifdef __KERNEL__ - -#include -#include -#include - -static inline int -futex_atomic_op_inuser (int encoded_op, int __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret; - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - case FUTEX_OP_ADD: - case FUTEX_OP_OR: - case FUTEX_OP_ANDN: - case FUTEX_OP_XOR: - default: - ret = -ENOSYS; - } - - dec_preempt_count(); - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -#endif -#endif diff --git a/include/asm-ppc64/futex.h b/include/asm-ppc64/futex.h deleted file mode 100644 index 266b460de44e..000000000000 --- a/include/asm-ppc64/futex.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ - __asm__ __volatile (SYNC_ON_SMP \ -"1: lwarx %0,0,%2\n" \ - insn \ -"2: stwcx. %1,0,%2\n\ - bne- 1b\n\ - li %1,0\n\ -3: .section .fixup,\"ax\"\n\ -4: li %1,%3\n\ - b 3b\n\ - .previous\n\ - .section __ex_table,\"a\"\n\ - .align 3\n\ - .llong 1b,4b,2b,4b\n\ - .previous" \ - : "=&r" (oldval), "=&r" (ret) \ - : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ - : "cr0", "memory") - -static inline int -futex_atomic_op_inuser (int encoded_op, int __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret; - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - __futex_atomic_op("", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_ADD: - __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_OR: - __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_ANDN: - __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_XOR: - __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - default: - ret = -ENOSYS; - } - - dec_preempt_count(); - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -#endif -#endif -- cgit v1.2.3 From 59ce20bb341282d5ecf17fd8b0ac093dd6350e5e Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 14:49:47 +1100 Subject: merge filename and modify references to iseries/it_lp_reg_save.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/lpardata.c | 2 +- include/asm-powerpc/iseries/it_lp_reg_save.h | 84 ++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/ItLpRegSave.h | 84 ---------------------------- include/asm-ppc64/paca.h | 2 +- 4 files changed, 86 insertions(+), 86 deletions(-) create mode 100644 include/asm-powerpc/iseries/it_lp_reg_save.h delete mode 100644 include/asm-ppc64/iSeries/ItLpRegSave.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index dfe38eb4036d..6cd25b9b5e5a 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/asm-powerpc/iseries/it_lp_reg_save.h b/include/asm-powerpc/iseries/it_lp_reg_save.h new file mode 100644 index 000000000000..1b3087e76205 --- /dev/null +++ b/include/asm-powerpc/iseries/it_lp_reg_save.h @@ -0,0 +1,84 @@ +/* + * ItLpRegSave.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITLPREGSAVE_H +#define _ITLPREGSAVE_H + +/* + * This control block contains the data that is shared between PLIC + * and the OS + */ + +struct ItLpRegSave { + u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003 + u16 xSize; // Size of this class 004-005 + u8 xInUse; // Area is live 006-007 + u8 xRsvd1[9]; // Reserved 007-00F + + u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F + u32 xCTRL; // Control Register 170-173 + u32 xDEC; // Decrementer 174-177 + u32 xFPSCR; // FP Status and Control Reg 178-17B + u32 xPVR; // Processor Version Number 17C-17F + + u64 xMMCR0; // Monitor Mode Control Reg 0 180-187 + u32 xPMC1; // Perf Monitor Counter 1 188-18B + u32 xPMC2; // Perf Monitor Counter 2 18C-18F + u32 xPMC3; // Perf Monitor Counter 3 190-193 + u32 xPMC4; // Perf Monitor Counter 4 194-197 + u32 xPIR; // Processor ID Reg 198-19B + + u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F + u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3 + u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7 + u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB + u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF + u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3 + u32 xTSC; // Thread Switch Control 1B4-1B7 + u32 xTST; // Thread Switch Timeout 1B8-1BB + u32 xRsvd; // Reserved 1BC-1BF + + u64 xACCR; // Address Compare Control Reg 1C0-1C7 + u64 xIMR; // Instruction Match Register 1C8-1CF + u64 xSDR1; // Storage Description Reg 1 1D0-1D7 + u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF + u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7 + u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF + u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7 + u64 xTB; // Time Base Register 1F8-1FF + + u64 xFPR[32]; // Floating Point Registers 200-2FF + + u64 xMSR; // Machine State Register 300-307 + u64 xNIA; // Next Instruction Address 308-30F + + u64 xDABR; // Data Address Breakpoint Reg 310-317 + u64 xIABR; // Inst Address Breakpoint Reg 318-31F + + u64 xHID0; // HW Implementation Dependent0 320-327 + + u64 xHID4; // HW Implementation Dependent4 328-32F + u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337 + u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F + u64 xSDAR; // Sample Data Address Register 340-347 + u64 xSIAR; // Sample Inst Address Register 348-34F + + u8 xRsvd3[176]; // Reserved 350-3FF +}; + +#endif /* _ITLPREGSAVE_H */ diff --git a/include/asm-ppc64/iSeries/ItLpRegSave.h b/include/asm-ppc64/iSeries/ItLpRegSave.h deleted file mode 100644 index 1b3087e76205..000000000000 --- a/include/asm-ppc64/iSeries/ItLpRegSave.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ItLpRegSave.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _ITLPREGSAVE_H -#define _ITLPREGSAVE_H - -/* - * This control block contains the data that is shared between PLIC - * and the OS - */ - -struct ItLpRegSave { - u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003 - u16 xSize; // Size of this class 004-005 - u8 xInUse; // Area is live 006-007 - u8 xRsvd1[9]; // Reserved 007-00F - - u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F - u32 xCTRL; // Control Register 170-173 - u32 xDEC; // Decrementer 174-177 - u32 xFPSCR; // FP Status and Control Reg 178-17B - u32 xPVR; // Processor Version Number 17C-17F - - u64 xMMCR0; // Monitor Mode Control Reg 0 180-187 - u32 xPMC1; // Perf Monitor Counter 1 188-18B - u32 xPMC2; // Perf Monitor Counter 2 18C-18F - u32 xPMC3; // Perf Monitor Counter 3 190-193 - u32 xPMC4; // Perf Monitor Counter 4 194-197 - u32 xPIR; // Processor ID Reg 198-19B - - u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F - u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3 - u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7 - u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB - u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF - u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3 - u32 xTSC; // Thread Switch Control 1B4-1B7 - u32 xTST; // Thread Switch Timeout 1B8-1BB - u32 xRsvd; // Reserved 1BC-1BF - - u64 xACCR; // Address Compare Control Reg 1C0-1C7 - u64 xIMR; // Instruction Match Register 1C8-1CF - u64 xSDR1; // Storage Description Reg 1 1D0-1D7 - u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF - u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7 - u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF - u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7 - u64 xTB; // Time Base Register 1F8-1FF - - u64 xFPR[32]; // Floating Point Registers 200-2FF - - u64 xMSR; // Machine State Register 300-307 - u64 xNIA; // Next Instruction Address 308-30F - - u64 xDABR; // Data Address Breakpoint Reg 310-317 - u64 xIABR; // Inst Address Breakpoint Reg 318-31F - - u64 xHID0; // HW Implementation Dependent0 320-327 - - u64 xHID4; // HW Implementation Dependent4 328-32F - u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337 - u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F - u64 xSDAR; // Sample Data Address Register 340-347 - u64 xSIAR; // Sample Inst Address Register 348-34F - - u8 xRsvd3[176]; // Reserved 350-3FF -}; - -#endif /* _ITLPREGSAVE_H */ diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h index 2f0f36f73d38..f68fe91debaf 100644 --- a/include/asm-ppc64/paca.h +++ b/include/asm-ppc64/paca.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include register struct paca_struct *local_paca asm("r13"); -- cgit v1.2.3 From f2cad7a8cdbe66d313059824d61ef1f455031566 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 2 Nov 2005 03:10:43 +0000 Subject: [PATCH] ppc bug.h namespace pollution DATA_TYPE is really not a good thing to put into header that gets included all over the tree... Just make the cast always (long) and get rid of DATA_TYPE altogether. Signed-off-by: Al Viro Signed-off-by: Paul Mackerras --- include/asm-powerpc/bug.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h index 943e3d7dbcc7..f49f46271ba6 100644 --- a/include/asm-powerpc/bug.h +++ b/include/asm-powerpc/bug.h @@ -15,12 +15,10 @@ #define BUG_TABLE_ENTRY(label, line, file, func) \ ".llong " #label ", " #line ", " #file ", " #func "\n" #define TRAP_OP(ra, rb) "1: tdnei " #ra ", " #rb "\n" -#define DATA_TYPE long long #else #define BUG_TABLE_ENTRY(label, line, file, func) \ ".long " #label ", " #line ", " #file ", " #func "\n" #define TRAP_OP(ra, rb) "1: twnei " #ra ", " #rb "\n" -#define DATA_TYPE int #endif /* __powerpc64__ */ struct bug_entry { @@ -55,7 +53,7 @@ struct bug_entry *find_bug(unsigned long bugaddr); ".section __bug_table,\"a\"\n\t" \ BUG_TABLE_ENTRY(1b,%1,%2,%3) \ ".previous" \ - : : "r" ((DATA_TYPE)(x)), "i" (__LINE__), \ + : : "r" ((long)(x)), "i" (__LINE__), \ "i" (__FILE__), "i" (__FUNCTION__)); \ } while (0) @@ -65,7 +63,7 @@ struct bug_entry *find_bug(unsigned long bugaddr); ".section __bug_table,\"a\"\n\t" \ BUG_TABLE_ENTRY(1b,%1,%2,%3) \ ".previous" \ - : : "r" ((DATA_TYPE)(x)), \ + : : "r" ((long)(x)), \ "i" (__LINE__ + BUG_WARNING_TRAP), \ "i" (__FILE__), "i" (__FUNCTION__)); \ } while (0) -- cgit v1.2.3 From c43a55ff4e55d1bcfdf0cadfe2f00281e156c436 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 15:02:47 +1100 Subject: merge filename and modify references to iseries/lpar_map.h Signed-off-by: Kelly Daly --- arch/powerpc/kernel/head_64.S | 2 +- arch/powerpc/kernel/lparmap.c | 2 +- arch/powerpc/platforms/iseries/lpardata.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/ppc64/kernel/head.S | 2 +- include/asm-powerpc/iseries/lpar_map.h | 83 +++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/LparMap.h | 83 ------------------------------- 7 files changed, 88 insertions(+), 88 deletions(-) create mode 100644 include/asm-powerpc/iseries/lpar_map.h delete mode 100644 include/asm-ppc64/iSeries/LparMap.h (limited to 'include') diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 147215a0d6c0..ba30e3177b05 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #ifdef CONFIG_PPC_ISERIES diff --git a/arch/powerpc/kernel/lparmap.c b/arch/powerpc/kernel/lparmap.c index b81de286df5e..eded971d1bf9 100644 --- a/arch/powerpc/kernel/lparmap.c +++ b/arch/powerpc/kernel/lparmap.c @@ -8,7 +8,7 @@ */ #include #include -#include +#include const struct LparMap __attribute__((__section__(".text"))) xLparMap = { .xNumberEsids = HvEsidsToMap, diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index 6cd25b9b5e5a..608431a22607 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 9a9e54b736d3..758f5b50628a 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include "setup.h" #include "irq.h" diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 929f9f42cf7a..0b65efe1682e 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #ifdef CONFIG_PPC_ISERIES diff --git a/include/asm-powerpc/iseries/lpar_map.h b/include/asm-powerpc/iseries/lpar_map.h new file mode 100644 index 000000000000..a6840b186d03 --- /dev/null +++ b/include/asm-powerpc/iseries/lpar_map.h @@ -0,0 +1,83 @@ +/* + * LparMap.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _LPARMAP_H +#define _LPARMAP_H + +#ifndef __ASSEMBLY__ + +#include + +/* + * The iSeries hypervisor will set up mapping for one or more + * ESID/VSID pairs (in SLB/segment registers) and will set up + * mappings of one or more ranges of pages to VAs. + * We will have the hypervisor set up the ESID->VSID mapping + * for the four kernel segments (C-F). With shared processors, + * the hypervisor will clear all segment registers and reload + * these four whenever the processor is switched from one + * partition to another. + */ + +/* The Vsid and Esid identified below will be used by the hypervisor + * to set up a memory mapping for part of the load area before giving + * control to the Linux kernel. The load area is 64 MB, but this must + * not attempt to map the whole load area. The Hashed Page Table may + * need to be located within the load area (if the total partition size + * is 64 MB), but cannot be mapped. Typically, this should specify + * to map half (32 MB) of the load area. + * + * The hypervisor will set up page table entries for the number of + * pages specified. + * + * In 32-bit mode, the hypervisor will load all four of the + * segment registers (identified by the low-order four bits of the + * Esid field. In 64-bit mode, the hypervisor will load one SLB + * entry to map the Esid to the Vsid. +*/ + +#define HvEsidsToMap 2 +#define HvRangesToMap 1 + +/* Hypervisor initially maps 32MB of the load area */ +#define HvPagesToMap 8192 + +struct LparMap { + u64 xNumberEsids; // Number of ESID/VSID pairs + u64 xNumberRanges; // Number of VA ranges to map + u64 xSegmentTableOffs; // Page number within load area of seg table + u64 xRsvd[5]; + struct { + u64 xKernelEsid; // Esid used to map kernel load + u64 xKernelVsid; // Vsid used to map kernel load + } xEsids[HvEsidsToMap]; + struct { + u64 xPages; // Number of pages to be mapped + u64 xOffset; // Offset from start of load area + u64 xVPN; // Virtual Page Number + } xRanges[HvRangesToMap]; +}; + +extern const struct LparMap xLparMap; + +#endif /* __ASSEMBLY__ */ + +/* the fixed address where the LparMap exists */ +#define LPARMAP_PHYS 0x7000 + +#endif /* _LPARMAP_H */ diff --git a/include/asm-ppc64/iSeries/LparMap.h b/include/asm-ppc64/iSeries/LparMap.h deleted file mode 100644 index a6840b186d03..000000000000 --- a/include/asm-ppc64/iSeries/LparMap.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * LparMap.h - * Copyright (C) 2001 Mike Corrigan IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _LPARMAP_H -#define _LPARMAP_H - -#ifndef __ASSEMBLY__ - -#include - -/* - * The iSeries hypervisor will set up mapping for one or more - * ESID/VSID pairs (in SLB/segment registers) and will set up - * mappings of one or more ranges of pages to VAs. - * We will have the hypervisor set up the ESID->VSID mapping - * for the four kernel segments (C-F). With shared processors, - * the hypervisor will clear all segment registers and reload - * these four whenever the processor is switched from one - * partition to another. - */ - -/* The Vsid and Esid identified below will be used by the hypervisor - * to set up a memory mapping for part of the load area before giving - * control to the Linux kernel. The load area is 64 MB, but this must - * not attempt to map the whole load area. The Hashed Page Table may - * need to be located within the load area (if the total partition size - * is 64 MB), but cannot be mapped. Typically, this should specify - * to map half (32 MB) of the load area. - * - * The hypervisor will set up page table entries for the number of - * pages specified. - * - * In 32-bit mode, the hypervisor will load all four of the - * segment registers (identified by the low-order four bits of the - * Esid field. In 64-bit mode, the hypervisor will load one SLB - * entry to map the Esid to the Vsid. -*/ - -#define HvEsidsToMap 2 -#define HvRangesToMap 1 - -/* Hypervisor initially maps 32MB of the load area */ -#define HvPagesToMap 8192 - -struct LparMap { - u64 xNumberEsids; // Number of ESID/VSID pairs - u64 xNumberRanges; // Number of VA ranges to map - u64 xSegmentTableOffs; // Page number within load area of seg table - u64 xRsvd[5]; - struct { - u64 xKernelEsid; // Esid used to map kernel load - u64 xKernelVsid; // Vsid used to map kernel load - } xEsids[HvEsidsToMap]; - struct { - u64 xPages; // Number of pages to be mapped - u64 xOffset; // Offset from start of load area - u64 xVPN; // Virtual Page Number - } xRanges[HvRangesToMap]; -}; - -extern const struct LparMap xLparMap; - -#endif /* __ASSEMBLY__ */ - -/* the fixed address where the LparMap exists */ -#define LPARMAP_PHYS 0x7000 - -#endif /* _LPARMAP_H */ -- cgit v1.2.3 From 6cbbdabb0163471590bf0a57766e3ea5d920d26e Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 15:07:51 +1100 Subject: merge filename and modify references to iseries/iseries_io.h Signed-off-by: Kelly Daly --- include/asm-powerpc/iseries/iseries_io.h | 49 ++++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/iSeries_io.h | 49 -------------------------------- include/asm-ppc64/io.h | 2 +- 3 files changed, 50 insertions(+), 50 deletions(-) create mode 100644 include/asm-powerpc/iseries/iseries_io.h delete mode 100644 include/asm-ppc64/iSeries/iSeries_io.h (limited to 'include') diff --git a/include/asm-powerpc/iseries/iseries_io.h b/include/asm-powerpc/iseries/iseries_io.h new file mode 100644 index 000000000000..9f79413342b3 --- /dev/null +++ b/include/asm-powerpc/iseries/iseries_io.h @@ -0,0 +1,49 @@ +#ifndef _ISERIES_IO_H +#define _ISERIES_IO_H + +#include + +#ifdef CONFIG_PPC_ISERIES +#include +/* + * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000. + * + * Remaps the io.h for the iSeries Io + * Copyright (C) 2000 Allan H Trautman, IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + * Change Activity: + * Created December 28, 2000 + * End Change Activity + */ + +extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress); +extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress); +extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress); +extern void iSeries_Write_Byte(u8 IoData, volatile void __iomem * IoAddress); +extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress); +extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress); + +extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n); +extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, + size_t n); +extern void iSeries_memcpy_fromio(void *dest, + const volatile void __iomem *source, size_t n); + +#endif /* CONFIG_PPC_ISERIES */ +#endif /* _ISERIES_IO_H */ diff --git a/include/asm-ppc64/iSeries/iSeries_io.h b/include/asm-ppc64/iSeries/iSeries_io.h deleted file mode 100644 index 9f79413342b3..000000000000 --- a/include/asm-ppc64/iSeries/iSeries_io.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _ISERIES_IO_H -#define _ISERIES_IO_H - -#include - -#ifdef CONFIG_PPC_ISERIES -#include -/* - * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000. - * - * Remaps the io.h for the iSeries Io - * Copyright (C) 2000 Allan H Trautman, IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - * Change Activity: - * Created December 28, 2000 - * End Change Activity - */ - -extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress); -extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress); -extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress); -extern void iSeries_Write_Byte(u8 IoData, volatile void __iomem * IoAddress); -extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress); -extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress); - -extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n); -extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, - size_t n); -extern void iSeries_memcpy_fromio(void *dest, - const volatile void __iomem *source, size_t n); - -#endif /* CONFIG_PPC_ISERIES */ -#endif /* _ISERIES_IO_H */ diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h index bd7c9532d77b..77fc07c3c6bd 100644 --- a/include/asm-ppc64/io.h +++ b/include/asm-ppc64/io.h @@ -13,7 +13,7 @@ #include #include #ifdef CONFIG_PPC_ISERIES -#include +#include #endif #include #include -- cgit v1.2.3 From bbc8b628b07e191624a74ce99fe36681cd70af37 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 15:10:38 +1100 Subject: merge filename and modify references to iSeries/mf.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/pci.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 2 +- drivers/net/iseries_veth.c | 2 +- include/asm-powerpc/iseries/mf.h | 57 ++++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/mf.h | 57 -------------------------------- 7 files changed, 62 insertions(+), 62 deletions(-) create mode 100644 include/asm-powerpc/iseries/mf.h delete mode 100644 include/asm-ppc64/iSeries/mf.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 689f65a49c00..59916393ddeb 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index a39b7a720101..7d7d5884343f 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 758f5b50628a..d955e950a74c 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 6fa39ae5f12c..72dfcb6d4dda 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include /* Status of the path to each other partition in the system. diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 1070140d9f59..d86d8f055a6c 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -72,7 +72,7 @@ #include #include -#include +#include #include #include diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h new file mode 100644 index 000000000000..166cd73f5c15 --- /dev/null +++ b/include/asm-powerpc/iseries/mf.h @@ -0,0 +1,57 @@ +/* + * mf.h + * Copyright (C) 2001 Troy D. Armstrong IBM Corporation + * Copyright (C) 2004 Stephen Rothwell IBM Corporation + * + * This modules exists as an interface between a Linux secondary partition + * running on an iSeries and the primary partition's Virtual Service + * Processor (VSP) object. The VSP has final authority over powering on/off + * all partitions in the iSeries. It also provides miscellaneous low-level + * machine facility type operations. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ASM_PPC64_ISERIES_MF_H +#define _ASM_PPC64_ISERIES_MF_H + +#include + +#include +#include + +struct rtc_time; + +typedef void (*MFCompleteHandler)(void *clientToken, int returnCode); + +extern void mf_allocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, + unsigned size, unsigned amount, MFCompleteHandler hdlr, + void *userToken); +extern void mf_deallocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, + unsigned count, MFCompleteHandler hdlr, void *userToken); + +extern void mf_power_off(void); +extern void mf_reboot(void); + +extern void mf_display_src(u32 word); +extern void mf_display_progress(u16 value); +extern void mf_clear_src(void); + +extern void mf_init(void); + +extern int mf_get_rtc(struct rtc_time *tm); +extern int mf_get_boot_rtc(struct rtc_time *tm); +extern int mf_set_rtc(struct rtc_time *tm); + +#endif /* _ASM_PPC64_ISERIES_MF_H */ diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h deleted file mode 100644 index 166cd73f5c15..000000000000 --- a/include/asm-ppc64/iSeries/mf.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * mf.h - * Copyright (C) 2001 Troy D. Armstrong IBM Corporation - * Copyright (C) 2004 Stephen Rothwell IBM Corporation - * - * This modules exists as an interface between a Linux secondary partition - * running on an iSeries and the primary partition's Virtual Service - * Processor (VSP) object. The VSP has final authority over powering on/off - * all partitions in the iSeries. It also provides miscellaneous low-level - * machine facility type operations. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _ASM_PPC64_ISERIES_MF_H -#define _ASM_PPC64_ISERIES_MF_H - -#include - -#include -#include - -struct rtc_time; - -typedef void (*MFCompleteHandler)(void *clientToken, int returnCode); - -extern void mf_allocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, - unsigned size, unsigned amount, MFCompleteHandler hdlr, - void *userToken); -extern void mf_deallocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, - unsigned count, MFCompleteHandler hdlr, void *userToken); - -extern void mf_power_off(void); -extern void mf_reboot(void); - -extern void mf_display_src(u32 word); -extern void mf_display_progress(u16 value); -extern void mf_clear_src(void); - -extern void mf_init(void); - -extern int mf_get_rtc(struct rtc_time *tm); -extern int mf_get_boot_rtc(struct rtc_time *tm); -extern int mf_set_rtc(struct rtc_time *tm); - -#endif /* _ASM_PPC64_ISERIES_MF_H */ -- cgit v1.2.3 From b420677870e53b9b76ced91da207431f687eaed1 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 15:13:57 +1100 Subject: merge filename and modify references to iseries/vio.h Signed-off-by: Kelly Daly --- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/vio.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 2 +- drivers/block/viodasd.c | 2 +- drivers/cdrom/viocd.c | 2 +- drivers/char/viocons.c | 2 +- drivers/char/viotape.c | 4 +- drivers/scsi/ibmvscsi/iseries_vscsi.c | 2 +- include/asm-powerpc/iseries/vio.h | 130 +++++++++++++++++++++++++++++++ include/asm-ppc64/iSeries/vio.h | 130 ------------------------------- 10 files changed, 139 insertions(+), 139 deletions(-) create mode 100644 include/asm-powerpc/iseries/vio.h delete mode 100644 include/asm-ppc64/iSeries/vio.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 59916393ddeb..49e7e4b85847 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index d607ebaef270..c27a66876c2c 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 72dfcb6d4dda..fe97bfbf7463 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include /* Status of the path to each other partition in the system. * This is overkill, since we will only ever establish connections diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 436f169baf02..2d518aa2720a 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("iSeries Virtual DASD"); MODULE_AUTHOR("Dave Boutcher"); diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index cb87d270b6bb..b5191780ecca 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #define VIOCD_DEVICE "iseries/vcd" #define VIOCD_DEVICE_DEVFS "iseries/vcd" diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 694bab3b7bf7..98601c7d04a9 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -44,7 +44,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 3242b241d789..867cc4e418c7 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -29,7 +29,7 @@ * * All tape operations are performed by sending messages back and forth to * the OS/400 partition. The format of the messages is defined in - * iSeries/vio.h + * iseries/vio.h */ #include #include @@ -54,7 +54,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index ed89659ac3bf..1045872b0175 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -28,7 +28,7 @@ * hypervisor system or a converged hypervisor system. */ -#include +#include #include #include #include diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h new file mode 100644 index 000000000000..2b57dbf5c257 --- /dev/null +++ b/include/asm-powerpc/iseries/vio.h @@ -0,0 +1,130 @@ +/* -*- linux-c -*- + * drivers/char/vio.h + * + * iSeries Virtual I/O Message Path header + * + * Authors: Dave Boutcher + * Ryan Arnold + * Colin Devilbiss + * + * (C) Copyright 2000 IBM Corporation + * + * This header file is used by the iSeries virtual I/O device + * drivers. It defines the interfaces to the common functions + * (implemented in drivers/char/viopath.h) as well as defining + * common functions and structures. Currently (at the time I + * wrote this comment) the iSeries virtual I/O device drivers + * that use this are + * drivers/block/viodasd.c + * drivers/char/viocons.c + * drivers/char/viotape.c + * drivers/cdrom/viocd.c + * + * The iSeries virtual ethernet support (veth.c) uses a whole + * different set of functions. + * + * 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) anyu later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _ISERIES_VIO_H +#define _ISERIES_VIO_H + +#include +#include + +/* + * iSeries virtual I/O events use the subtype field in + * HvLpEvent to figure out what kind of vio event is coming + * in. We use a table to route these, and this defines + * the maximum number of distinct subtypes + */ +#define VIO_MAX_SUBTYPES 8 + +/* + * Each subtype can register a handler to process their events. + * The handler must have this interface. + */ +typedef void (vio_event_handler_t) (struct HvLpEvent * event); + +extern int viopath_open(HvLpIndex remoteLp, int subtype, int numReq); +extern int viopath_close(HvLpIndex remoteLp, int subtype, int numReq); +extern int vio_setHandler(int subtype, vio_event_handler_t * beh); +extern int vio_clearHandler(int subtype); +extern int viopath_isactive(HvLpIndex lp); +extern HvLpInstanceId viopath_sourceinst(HvLpIndex lp); +extern HvLpInstanceId viopath_targetinst(HvLpIndex lp); +extern void vio_set_hostlp(void); +extern void *vio_get_event_buffer(int subtype); +extern void vio_free_event_buffer(int subtype, void *buffer); + +extern HvLpIndex viopath_hostLp; +extern HvLpIndex viopath_ourLp; + +#define VIOCHAR_MAX_DATA 200 + +#define VIOMAJOR_SUBTYPE_MASK 0xff00 +#define VIOMINOR_SUBTYPE_MASK 0x00ff +#define VIOMAJOR_SUBTYPE_SHIFT 8 + +#define VIOVERSION 0x0101 + +/* + * This is the general structure for VIO errors; each module should have + * a table of them, and each table should be terminated by an entry of + * { 0, 0, NULL }. Then, to find a specific error message, a module + * should pass its local table and the return code. + */ +struct vio_error_entry { + u16 rc; + int errno; + const char *msg; +}; +extern const struct vio_error_entry *vio_lookup_rc( + const struct vio_error_entry *local_table, u16 rc); + +enum viosubtypes { + viomajorsubtype_monitor = 0x0100, + viomajorsubtype_blockio = 0x0200, + viomajorsubtype_chario = 0x0300, + viomajorsubtype_config = 0x0400, + viomajorsubtype_cdio = 0x0500, + viomajorsubtype_tape = 0x0600, + viomajorsubtype_scsi = 0x0700 +}; + +enum vioconfigsubtype { + vioconfigget = 0x0001, +}; + +enum viorc { + viorc_good = 0x0000, + viorc_noConnection = 0x0001, + viorc_noReceiver = 0x0002, + viorc_noBufferAvailable = 0x0003, + viorc_invalidMessageType = 0x0004, + viorc_invalidRange = 0x0201, + viorc_invalidToken = 0x0202, + viorc_DMAError = 0x0203, + viorc_useError = 0x0204, + viorc_releaseError = 0x0205, + viorc_invalidDisk = 0x0206, + viorc_openRejected = 0x0301 +}; + +struct device; + +extern struct device *iSeries_vio_dev; + +#endif /* _ISERIES_VIO_H */ diff --git a/include/asm-ppc64/iSeries/vio.h b/include/asm-ppc64/iSeries/vio.h deleted file mode 100644 index 2b57dbf5c257..000000000000 --- a/include/asm-ppc64/iSeries/vio.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- linux-c -*- - * drivers/char/vio.h - * - * iSeries Virtual I/O Message Path header - * - * Authors: Dave Boutcher - * Ryan Arnold - * Colin Devilbiss - * - * (C) Copyright 2000 IBM Corporation - * - * This header file is used by the iSeries virtual I/O device - * drivers. It defines the interfaces to the common functions - * (implemented in drivers/char/viopath.h) as well as defining - * common functions and structures. Currently (at the time I - * wrote this comment) the iSeries virtual I/O device drivers - * that use this are - * drivers/block/viodasd.c - * drivers/char/viocons.c - * drivers/char/viotape.c - * drivers/cdrom/viocd.c - * - * The iSeries virtual ethernet support (veth.c) uses a whole - * different set of functions. - * - * 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) anyu later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef _ISERIES_VIO_H -#define _ISERIES_VIO_H - -#include -#include - -/* - * iSeries virtual I/O events use the subtype field in - * HvLpEvent to figure out what kind of vio event is coming - * in. We use a table to route these, and this defines - * the maximum number of distinct subtypes - */ -#define VIO_MAX_SUBTYPES 8 - -/* - * Each subtype can register a handler to process their events. - * The handler must have this interface. - */ -typedef void (vio_event_handler_t) (struct HvLpEvent * event); - -extern int viopath_open(HvLpIndex remoteLp, int subtype, int numReq); -extern int viopath_close(HvLpIndex remoteLp, int subtype, int numReq); -extern int vio_setHandler(int subtype, vio_event_handler_t * beh); -extern int vio_clearHandler(int subtype); -extern int viopath_isactive(HvLpIndex lp); -extern HvLpInstanceId viopath_sourceinst(HvLpIndex lp); -extern HvLpInstanceId viopath_targetinst(HvLpIndex lp); -extern void vio_set_hostlp(void); -extern void *vio_get_event_buffer(int subtype); -extern void vio_free_event_buffer(int subtype, void *buffer); - -extern HvLpIndex viopath_hostLp; -extern HvLpIndex viopath_ourLp; - -#define VIOCHAR_MAX_DATA 200 - -#define VIOMAJOR_SUBTYPE_MASK 0xff00 -#define VIOMINOR_SUBTYPE_MASK 0x00ff -#define VIOMAJOR_SUBTYPE_SHIFT 8 - -#define VIOVERSION 0x0101 - -/* - * This is the general structure for VIO errors; each module should have - * a table of them, and each table should be terminated by an entry of - * { 0, 0, NULL }. Then, to find a specific error message, a module - * should pass its local table and the return code. - */ -struct vio_error_entry { - u16 rc; - int errno; - const char *msg; -}; -extern const struct vio_error_entry *vio_lookup_rc( - const struct vio_error_entry *local_table, u16 rc); - -enum viosubtypes { - viomajorsubtype_monitor = 0x0100, - viomajorsubtype_blockio = 0x0200, - viomajorsubtype_chario = 0x0300, - viomajorsubtype_config = 0x0400, - viomajorsubtype_cdio = 0x0500, - viomajorsubtype_tape = 0x0600, - viomajorsubtype_scsi = 0x0700 -}; - -enum vioconfigsubtype { - vioconfigget = 0x0001, -}; - -enum viorc { - viorc_good = 0x0000, - viorc_noConnection = 0x0001, - viorc_noReceiver = 0x0002, - viorc_noBufferAvailable = 0x0003, - viorc_invalidMessageType = 0x0004, - viorc_invalidRange = 0x0201, - viorc_invalidToken = 0x0202, - viorc_DMAError = 0x0203, - viorc_useError = 0x0204, - viorc_releaseError = 0x0205, - viorc_invalidDisk = 0x0206, - viorc_openRejected = 0x0301 -}; - -struct device; - -extern struct device *iSeries_vio_dev; - -#endif /* _ISERIES_VIO_H */ -- cgit v1.2.3 From 104dd65fef378773ec0510c788bd4b5ad6ea1121 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 2 Nov 2005 15:19:47 +1100 Subject: powerpc: clean up bug.h further This simplifies the macros which are different between 32-bit and 64-bit. It also fixes a couple of printks on the bug->line element, which is now a long. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/traps.c | 8 ++++---- include/asm-powerpc/bug.h | 26 ++++++++++++-------------- 2 files changed, 16 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index bb0d00284a7e..07e5ee40b870 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -749,22 +749,22 @@ static int check_bug_trap(struct pt_regs *regs) if (bug->line & BUG_WARNING_TRAP) { /* this is a WARN_ON rather than BUG/BUG_ON */ #ifdef CONFIG_XMON - xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", + xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n", bug->function, bug->file, bug->line & ~BUG_WARNING_TRAP); #endif /* CONFIG_XMON */ - printk(KERN_ERR "Badness in %s at %s:%d\n", + printk(KERN_ERR "Badness in %s at %s:%ld\n", bug->function, bug->file, bug->line & ~BUG_WARNING_TRAP); dump_stack(); return 1; } #ifdef CONFIG_XMON - xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n", + xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", bug->function, bug->file, bug->line); xmon(regs); #endif /* CONFIG_XMON */ - printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", + printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", bug->function, bug->file, bug->line); return 0; diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h index f49f46271ba6..d625ee55f957 100644 --- a/include/asm-powerpc/bug.h +++ b/include/asm-powerpc/bug.h @@ -12,13 +12,11 @@ #ifndef __ASSEMBLY__ #ifdef __powerpc64__ -#define BUG_TABLE_ENTRY(label, line, file, func) \ - ".llong " #label ", " #line ", " #file ", " #func "\n" -#define TRAP_OP(ra, rb) "1: tdnei " #ra ", " #rb "\n" +#define BUG_TABLE_ENTRY ".llong" +#define BUG_TRAP_OP "tdnei" #else -#define BUG_TABLE_ENTRY(label, line, file, func) \ - ".long " #label ", " #line ", " #file ", " #func "\n" -#define TRAP_OP(ra, rb) "1: twnei " #ra ", " #rb "\n" +#define BUG_TABLE_ENTRY ".long" +#define BUG_TRAP_OP "twnei" #endif /* __powerpc64__ */ struct bug_entry { @@ -41,17 +39,17 @@ struct bug_entry *find_bug(unsigned long bugaddr); #define BUG() do { \ __asm__ __volatile__( \ "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n\t" \ - BUG_TABLE_ENTRY(1b,%0,%1,%2) \ + ".section __bug_table,\"a\"\n" \ + "\t"BUG_TABLE_ENTRY" 1b,%0,%1,%2\n" \ ".previous" \ : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ } while (0) #define BUG_ON(x) do { \ __asm__ __volatile__( \ - TRAP_OP(%0,0) \ - ".section __bug_table,\"a\"\n\t" \ - BUG_TABLE_ENTRY(1b,%1,%2,%3) \ + "1: "BUG_TRAP_OP" %0,0\n" \ + ".section __bug_table,\"a\"\n" \ + "\t"BUG_TABLE_ENTRY" 1b,%1,%2,%3\n" \ ".previous" \ : : "r" ((long)(x)), "i" (__LINE__), \ "i" (__FILE__), "i" (__FUNCTION__)); \ @@ -59,9 +57,9 @@ struct bug_entry *find_bug(unsigned long bugaddr); #define WARN_ON(x) do { \ __asm__ __volatile__( \ - TRAP_OP(%0,0) \ - ".section __bug_table,\"a\"\n\t" \ - BUG_TABLE_ENTRY(1b,%1,%2,%3) \ + "1: "BUG_TRAP_OP" %0,0\n" \ + ".section __bug_table,\"a\"\n" \ + "\t"BUG_TABLE_ENTRY" 1b,%1,%2,%3\n" \ ".previous" \ : : "r" ((long)(x)), \ "i" (__LINE__ + BUG_WARNING_TRAP), \ -- cgit v1.2.3 From 10e8805716698596f5b6445d76bbb7ed1adb7295 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 15:22:37 +1100 Subject: fix incorrect dir Signed-off-by: Kelly Daly --- include/asm-powerpc/iseries/mf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h index 166cd73f5c15..dc6843e72aff 100644 --- a/include/asm-powerpc/iseries/mf.h +++ b/include/asm-powerpc/iseries/mf.h @@ -29,7 +29,7 @@ #include #include -#include +#include struct rtc_time; -- cgit v1.2.3 From 1fc8b4ef4e1a0d6f2e16581716a4ae6e16ad3a76 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 2 Nov 2005 14:48:36 +1100 Subject: [PATCH] powerpc: Merge (move) numnodes.h and sparsemem.h The ppc64 versions of numnodes.h and sparsemem.h can be safely moved to asm-powerpc with no changes apart from changing the #define to the standard _ASM_POWERPC_ form. There are no ppc32 versions of these files, because they only have any effect if CONFIG_SPARSEMEM is enabled, which it never can be on ppc32. Built and booted on pSeries (POWER5), built for 32-bit powermac. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/numnodes.h | 7 +++++++ include/asm-powerpc/sparsemem.h | 16 ++++++++++++++++ include/asm-ppc64/numnodes.h | 7 ------- include/asm-ppc64/sparsemem.h | 16 ---------------- 4 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 include/asm-powerpc/numnodes.h create mode 100644 include/asm-powerpc/sparsemem.h delete mode 100644 include/asm-ppc64/numnodes.h delete mode 100644 include/asm-ppc64/sparsemem.h (limited to 'include') diff --git a/include/asm-powerpc/numnodes.h b/include/asm-powerpc/numnodes.h new file mode 100644 index 000000000000..795533aca095 --- /dev/null +++ b/include/asm-powerpc/numnodes.h @@ -0,0 +1,7 @@ +#ifndef _ASM_POWERPC_MAX_NUMNODES_H +#define _ASM_POWERPC_MAX_NUMNODES_H + +/* Max 16 Nodes */ +#define NODES_SHIFT 4 + +#endif /* _ASM_POWERPC_MAX_NUMNODES_H */ diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h new file mode 100644 index 000000000000..1c95ab99deb3 --- /dev/null +++ b/include/asm-powerpc/sparsemem.h @@ -0,0 +1,16 @@ +#ifndef _ASM_POWERPC_SPARSEMEM_H +#define _ASM_POWERPC_SPARSEMEM_H 1 + +#ifdef CONFIG_SPARSEMEM +/* + * SECTION_SIZE_BITS 2^N: how big each section will be + * MAX_PHYSADDR_BITS 2^N: how much physical address space we have + * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space + */ +#define SECTION_SIZE_BITS 24 +#define MAX_PHYSADDR_BITS 38 +#define MAX_PHYSMEM_BITS 36 + +#endif /* CONFIG_SPARSEMEM */ + +#endif /* _ASM_POWERPC_SPARSEMEM_H */ diff --git a/include/asm-ppc64/numnodes.h b/include/asm-ppc64/numnodes.h deleted file mode 100644 index 75ae0b906708..000000000000 --- a/include/asm-ppc64/numnodes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -/* Max 16 Nodes */ -#define NODES_SHIFT 4 - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-ppc64/sparsemem.h b/include/asm-ppc64/sparsemem.h deleted file mode 100644 index c5bd47e57f17..000000000000 --- a/include/asm-ppc64/sparsemem.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ASM_PPC64_SPARSEMEM_H -#define _ASM_PPC64_SPARSEMEM_H 1 - -#ifdef CONFIG_SPARSEMEM -/* - * SECTION_SIZE_BITS 2^N: how big each section will be - * MAX_PHYSADDR_BITS 2^N: how much physical address space we have - * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space - */ -#define SECTION_SIZE_BITS 24 -#define MAX_PHYSADDR_BITS 38 -#define MAX_PHYSMEM_BITS 36 - -#endif /* CONFIG_SPARSEMEM */ - -#endif /* _ASM_PPC64_SPARSEMEM_H */ -- cgit v1.2.3 From 9933f299d0e9e7b12ed4260669653d04d5e752c7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 2 Nov 2005 15:13:20 +1100 Subject: [PATCH] powerpc: Move dart.h asm-ppc64/dart.h is included in exactly one place - arch/powerpc/sysdev/u3_iommu.c. This patch, therefore, moves it into arch/powerpc/sysdev. While we're at it, update the #ifndef/#define protecting the include, and the filename in the comments of u3_iommu.c. Built and booted on pSeries and G5, built for ppc32 powermac. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/dart.h | 59 ++++++++++++++++++++++++++++++++++++++++++ arch/powerpc/sysdev/u3_iommu.c | 5 ++-- include/asm-ppc64/dart.h | 59 ------------------------------------------ 3 files changed, 62 insertions(+), 61 deletions(-) create mode 100644 arch/powerpc/sysdev/dart.h delete mode 100644 include/asm-ppc64/dart.h (limited to 'include') diff --git a/arch/powerpc/sysdev/dart.h b/arch/powerpc/sysdev/dart.h new file mode 100644 index 000000000000..ea8f0d9eed8a --- /dev/null +++ b/arch/powerpc/sysdev/dart.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _POWERPC_SYSDEV_DART_H +#define _POWERPC_SYSDEV_DART_H + + +/* physical base of DART registers */ +#define DART_BASE 0xf8033000UL + +/* Offset from base to control register */ +#define DARTCNTL 0 +/* Offset from base to exception register */ +#define DARTEXCP 0x10 +/* Offset from base to TLB tag registers */ +#define DARTTAG 0x1000 + + +/* Control Register fields */ + +/* base address of table (pfn) */ +#define DARTCNTL_BASE_MASK 0xfffff +#define DARTCNTL_BASE_SHIFT 12 + +#define DARTCNTL_FLUSHTLB 0x400 +#define DARTCNTL_ENABLE 0x200 + +/* size of table in pages */ +#define DARTCNTL_SIZE_MASK 0x1ff +#define DARTCNTL_SIZE_SHIFT 0 + + +/* DART table fields */ + +#define DARTMAP_VALID 0x80000000 +#define DARTMAP_RPNMASK 0x00ffffff + + +#define DART_PAGE_SHIFT 12 +#define DART_PAGE_SIZE (1 << DART_PAGE_SHIFT) +#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_PAGE_SHIFT) + + +#endif /* _POWERPC_SYSDEV_DART_H */ diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c index fba871a1bda5..607722178c1a 100644 --- a/arch/powerpc/sysdev/u3_iommu.c +++ b/arch/powerpc/sysdev/u3_iommu.c @@ -1,5 +1,5 @@ /* - * arch/ppc64/kernel/u3_iommu.c + * arch/powerpc/sysdev/u3_iommu.c * * Copyright (C) 2004 Olof Johansson , IBM Corporation * @@ -44,9 +44,10 @@ #include #include #include -#include #include +#include "dart.h" + extern int iommu_force_on; /* Physical base address and size of the DART table */ diff --git a/include/asm-ppc64/dart.h b/include/asm-ppc64/dart.h deleted file mode 100644 index cdf8a2dec05f..000000000000 --- a/include/asm-ppc64/dart.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2004 Olof Johansson , IBM Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ASM_DART_H -#define _ASM_DART_H - - -/* physical base of DART registers */ -#define DART_BASE 0xf8033000UL - -/* Offset from base to control register */ -#define DARTCNTL 0 -/* Offset from base to exception register */ -#define DARTEXCP 0x10 -/* Offset from base to TLB tag registers */ -#define DARTTAG 0x1000 - - -/* Control Register fields */ - -/* base address of table (pfn) */ -#define DARTCNTL_BASE_MASK 0xfffff -#define DARTCNTL_BASE_SHIFT 12 - -#define DARTCNTL_FLUSHTLB 0x400 -#define DARTCNTL_ENABLE 0x200 - -/* size of table in pages */ -#define DARTCNTL_SIZE_MASK 0x1ff -#define DARTCNTL_SIZE_SHIFT 0 - - -/* DART table fields */ - -#define DARTMAP_VALID 0x80000000 -#define DARTMAP_RPNMASK 0x00ffffff - - -#define DART_PAGE_SHIFT 12 -#define DART_PAGE_SIZE (1 << DART_PAGE_SHIFT) -#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_PAGE_SHIFT) - - -#endif -- cgit v1.2.3 From ecb3ca2783d6e54d30dbf70a42fe995c27eeb212 Mon Sep 17 00:00:00 2001 From: Kelly Daly Date: Wed, 2 Nov 2005 15:53:01 +1100 Subject: modify defines according to _ASM_POWERPC_ISERIES_ Signed-off-by: Kelly Daly --- include/asm-powerpc/iseries/hv_call.h | 6 +++--- include/asm-powerpc/iseries/hv_call_event.h | 6 +++--- include/asm-powerpc/iseries/hv_call_sc.h | 6 +++--- include/asm-powerpc/iseries/hv_call_xm.h | 6 +++--- include/asm-powerpc/iseries/hv_lp_config.h | 6 +++--- include/asm-powerpc/iseries/hv_lp_event.h | 6 +++--- include/asm-powerpc/iseries/hv_types.h | 6 +++--- include/asm-powerpc/iseries/iseries_io.h | 6 +++--- include/asm-powerpc/iseries/it_exp_vpd_panel.h | 6 +++--- include/asm-powerpc/iseries/it_lp_naca.h | 6 +++--- include/asm-powerpc/iseries/it_lp_queue.h | 6 +++--- include/asm-powerpc/iseries/it_lp_reg_save.h | 4 ++-- include/asm-powerpc/iseries/lpar_map.h | 6 +++--- include/asm-powerpc/iseries/mf.h | 6 +++--- include/asm-powerpc/iseries/vio.h | 6 +++--- 15 files changed, 44 insertions(+), 44 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/iseries/hv_call.h b/include/asm-powerpc/iseries/hv_call.h index af59cc1e9691..e9f831c9a5e5 100644 --- a/include/asm-powerpc/iseries/hv_call.h +++ b/include/asm-powerpc/iseries/hv_call.h @@ -20,8 +20,8 @@ * This file contains the "hypervisor call" interface which is used to * drive the hypervisor from the OS. */ -#ifndef _HVCALL_H -#define _HVCALL_H +#ifndef _ASM_POWERPC_ISERIES_HV_CALL_H +#define _ASM_POWERPC_ISERIES_HV_CALL_H #include #include @@ -110,4 +110,4 @@ static inline void HvCall_sendIPI(struct paca_struct *targetPaca) HvCall1(HvCallBaseSendIPI, targetPaca->paca_index); } -#endif /* _HVCALL_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_CALL_H */ diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h index c2770b056ae8..46763a30590a 100644 --- a/include/asm-powerpc/iseries/hv_call_event.h +++ b/include/asm-powerpc/iseries/hv_call_event.h @@ -20,8 +20,8 @@ * This file contains the "hypervisor call" interface which is used to * drive the hypervisor from the OS. */ -#ifndef _HVCALLEVENT_H -#define _HVCALLEVENT_H +#ifndef _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H +#define _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H #include #include @@ -250,4 +250,4 @@ static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote, return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir); } -#endif /* _HVCALLEVENT_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H */ diff --git a/include/asm-powerpc/iseries/hv_call_sc.h b/include/asm-powerpc/iseries/hv_call_sc.h index a62cef3822f9..dec7e9d9ab78 100644 --- a/include/asm-powerpc/iseries/hv_call_sc.h +++ b/include/asm-powerpc/iseries/hv_call_sc.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _HVCALLSC_H -#define _HVCALLSC_H +#ifndef _ASM_POWERPC_ISERIES_HV_CALL_SC_H +#define _ASM_POWERPC_ISERIES_HV_CALL_SC_H #include @@ -48,4 +48,4 @@ extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64); extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64); extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64); -#endif /* _HVCALLSC_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_CALL_SC_H */ diff --git a/include/asm-powerpc/iseries/hv_call_xm.h b/include/asm-powerpc/iseries/hv_call_xm.h index fd36b11612f8..ca9202cb01ed 100644 --- a/include/asm-powerpc/iseries/hv_call_xm.h +++ b/include/asm-powerpc/iseries/hv_call_xm.h @@ -2,8 +2,8 @@ * This file contains the "hypervisor call" interface which is used to * drive the hypervisor from SLIC. */ -#ifndef _HVCALLXM_H -#define _HVCALLXM_H +#ifndef _ASM_POWERPC_ISERIES_HV_CALL_XM_H +#define _ASM_POWERPC_ISERIES_HV_CALL_XM_H #include #include @@ -75,4 +75,4 @@ static inline u64 HvCallXm_loadTod(void) return HvCall0(HvCallXmLoadTod); } -#endif /* _HVCALLXM_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_CALL_XM_H */ diff --git a/include/asm-powerpc/iseries/hv_lp_config.h b/include/asm-powerpc/iseries/hv_lp_config.h index db577f079f25..bc00f036bca0 100644 --- a/include/asm-powerpc/iseries/hv_lp_config.h +++ b/include/asm-powerpc/iseries/hv_lp_config.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _HVLPCONFIG_H -#define _HVLPCONFIG_H +#ifndef _ASM_POWERPC_ISERIES_HV_LP_CONFIG_H +#define _ASM_POWERPC_ISERIES_HV_LP_CONFIG_H /* * This file contains the interface to the LPAR configuration data @@ -135,4 +135,4 @@ static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp) return HvCall1(HvCallCfgGetHostingLpIndex, lp); } -#endif /* _HVLPCONFIG_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_LP_CONFIG_H */ diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h index 2a3b773854b1..499ab1ad0185 100644 --- a/include/asm-powerpc/iseries/hv_lp_event.h +++ b/include/asm-powerpc/iseries/hv_lp_event.h @@ -19,8 +19,8 @@ /* This file contains the class for HV events in the system. */ -#ifndef _HVLPEVENT_H -#define _HVLPEVENT_H +#ifndef _ASM_POWERPC_ISERIES_HV_LP_EVENT_H +#define _ASM_POWERPC_ISERIES_HV_LP_EVENT_H #include #include @@ -139,4 +139,4 @@ extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex); #define HvLpDma_Rc_InvalidAddress 4 #define HvLpDma_Rc_InvalidLength 5 -#endif /* _HVLPEVENT_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_LP_EVENT_H */ diff --git a/include/asm-powerpc/iseries/hv_types.h b/include/asm-powerpc/iseries/hv_types.h index b1ef2b4cb3e3..c38f7e3d01dc 100644 --- a/include/asm-powerpc/iseries/hv_types.h +++ b/include/asm-powerpc/iseries/hv_types.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _HVTYPES_H -#define _HVTYPES_H +#ifndef _ASM_POWERPC_ISERIES_HV_TYPES_H +#define _ASM_POWERPC_ISERIES_HV_TYPES_H /* * General typedefs for the hypervisor. @@ -110,4 +110,4 @@ struct HvLpBufferList { u64 len; }; -#endif /* _HVTYPES_H */ +#endif /* _ASM_POWERPC_ISERIES_HV_TYPES_H */ diff --git a/include/asm-powerpc/iseries/iseries_io.h b/include/asm-powerpc/iseries/iseries_io.h index 9f79413342b3..56b2113ff0f5 100644 --- a/include/asm-powerpc/iseries/iseries_io.h +++ b/include/asm-powerpc/iseries/iseries_io.h @@ -1,5 +1,5 @@ -#ifndef _ISERIES_IO_H -#define _ISERIES_IO_H +#ifndef _ASM_POWERPC_ISERIES_ISERIES_IO_H +#define _ASM_POWERPC_ISERIES_ISERIES_IO_H #include @@ -46,4 +46,4 @@ extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n); #endif /* CONFIG_PPC_ISERIES */ -#endif /* _ISERIES_IO_H */ +#endif /* _ASM_POWERPC_ISERIES_ISERIES_IO_H */ diff --git a/include/asm-powerpc/iseries/it_exp_vpd_panel.h b/include/asm-powerpc/iseries/it_exp_vpd_panel.h index 4c546a8802b4..66a17a230c52 100644 --- a/include/asm-powerpc/iseries/it_exp_vpd_panel.h +++ b/include/asm-powerpc/iseries/it_exp_vpd_panel.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ITEXTVPDPANEL_H -#define _ITEXTVPDPANEL_H +#ifndef _ASM_POWERPC_ISERIES_IT_EXT_VPD_PANEL_H +#define _ASM_POWERPC_ISERIES_IT_EXT_VPD_PANEL_H /* * This struct maps the panel information @@ -49,4 +49,4 @@ struct ItExtVpdPanel { extern struct ItExtVpdPanel xItExtVpdPanel; -#endif /* _ITEXTVPDPANEL_H */ +#endif /* _ASM_POWERPC_ISERIES_IT_EXT_VPD_PANEL_H */ diff --git a/include/asm-powerpc/iseries/it_lp_naca.h b/include/asm-powerpc/iseries/it_lp_naca.h index 225d0176779d..c3ef1de45d82 100644 --- a/include/asm-powerpc/iseries/it_lp_naca.h +++ b/include/asm-powerpc/iseries/it_lp_naca.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ITLPNACA_H -#define _ITLPNACA_H +#ifndef _ASM_POWERPC_ISERIES_IT_LP_NACA_H +#define _ASM_POWERPC_ISERIES_IT_LP_NACA_H #include @@ -77,4 +77,4 @@ struct ItLpNaca { extern struct ItLpNaca itLpNaca; -#endif /* _ITLPNACA_H */ +#endif /* _ASM_POWERPC_ISERIES_IT_LP_NACA_H */ diff --git a/include/asm-powerpc/iseries/it_lp_queue.h b/include/asm-powerpc/iseries/it_lp_queue.h index 69b26ad74135..a60d03afbf95 100644 --- a/include/asm-powerpc/iseries/it_lp_queue.h +++ b/include/asm-powerpc/iseries/it_lp_queue.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ITLPQUEUE_H -#define _ITLPQUEUE_H +#ifndef _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H +#define _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H /* * This control block defines the simple LP queue structure that is @@ -78,4 +78,4 @@ extern int hvlpevent_is_pending(void); extern void process_hvlpevents(struct pt_regs *); extern void setup_hvlpevent_queue(void); -#endif /* _ITLPQUEUE_H */ +#endif /* _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H */ diff --git a/include/asm-powerpc/iseries/it_lp_reg_save.h b/include/asm-powerpc/iseries/it_lp_reg_save.h index 1b3087e76205..288044b702de 100644 --- a/include/asm-powerpc/iseries/it_lp_reg_save.h +++ b/include/asm-powerpc/iseries/it_lp_reg_save.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ITLPREGSAVE_H -#define _ITLPREGSAVE_H +#ifndef _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H +#define _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H /* * This control block contains the data that is shared between PLIC diff --git a/include/asm-powerpc/iseries/lpar_map.h b/include/asm-powerpc/iseries/lpar_map.h index a6840b186d03..84fc321615bf 100644 --- a/include/asm-powerpc/iseries/lpar_map.h +++ b/include/asm-powerpc/iseries/lpar_map.h @@ -16,8 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _LPARMAP_H -#define _LPARMAP_H +#ifndef _ASM_POWERPC_ISERIES_LPAR_MAP_H +#define _ASM_POWERPC_ISERIES_LPAR_MAP_H #ifndef __ASSEMBLY__ @@ -80,4 +80,4 @@ extern const struct LparMap xLparMap; /* the fixed address where the LparMap exists */ #define LPARMAP_PHYS 0x7000 -#endif /* _LPARMAP_H */ +#endif /* _ASM_POWERPC_ISERIES_LPAR_MAP_H */ diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h index dc6843e72aff..e7bd57a03fb1 100644 --- a/include/asm-powerpc/iseries/mf.h +++ b/include/asm-powerpc/iseries/mf.h @@ -23,8 +23,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_PPC64_ISERIES_MF_H -#define _ASM_PPC64_ISERIES_MF_H +#ifndef _ASM_POWERPC_ISERIES_MF_H +#define _ASM_POWERPC_ISERIES_MF_H #include @@ -54,4 +54,4 @@ extern int mf_get_rtc(struct rtc_time *tm); extern int mf_get_boot_rtc(struct rtc_time *tm); extern int mf_set_rtc(struct rtc_time *tm); -#endif /* _ASM_PPC64_ISERIES_MF_H */ +#endif /* _ASM_POWERPC_ISERIES_MF_H */ diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h index 2b57dbf5c257..7e3a469420dd 100644 --- a/include/asm-powerpc/iseries/vio.h +++ b/include/asm-powerpc/iseries/vio.h @@ -38,8 +38,8 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#ifndef _ISERIES_VIO_H -#define _ISERIES_VIO_H +#ifndef _ASM_POWERPC_ISERIES_VIO_H +#define _ASM_POWERPC_ISERIES_VIO_H #include #include @@ -127,4 +127,4 @@ struct device; extern struct device *iSeries_vio_dev; -#endif /* _ISERIES_VIO_H */ +#endif /* _ASM_POWERPC_ISERIES_VIO_H */ -- cgit v1.2.3 From f11b7bd88f8b41f0986498ffa11ffff1c3e513ca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 1 Nov 2005 15:30:26 +1100 Subject: [PATCH] powerpc: Move naca.h to platforms/iseries These days, the NACA only exists on iSeries. Therefore, this patch moves naca.h from include/asm-ppc64 to arch/powerpc/platforms/iseries. There was one file including naca.h outside of platforms/iseries - arch/ppc64/kernel/udbg_scc.c. However, that's obviously a hangover from older days. The include is not necessary, so this patch simply removes it. Built and booted on iSeries, built for G5 (which uses udbg_scc.o). Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/lpardata.c | 2 +- arch/powerpc/platforms/iseries/naca.h | 24 ++++++++++++++++++++++++ arch/powerpc/platforms/iseries/release_data.h | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/ppc64/kernel/udbg_scc.c | 1 - include/asm-ppc64/naca.h | 24 ------------------------ 6 files changed, 27 insertions(+), 28 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/naca.h delete mode 100644 include/asm-ppc64/naca.h (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c index ed2ffee6f731..e856947bd16d 100644 --- a/arch/powerpc/platforms/iseries/lpardata.c +++ b/arch/powerpc/platforms/iseries/lpardata.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -23,6 +22,7 @@ #include #include +#include "naca.h" #include "vpd_areas.h" #include "spcomm_area.h" #include "ipl_parms.h" diff --git a/arch/powerpc/platforms/iseries/naca.h b/arch/powerpc/platforms/iseries/naca.h new file mode 100644 index 000000000000..ab2372eb8d2e --- /dev/null +++ b/arch/powerpc/platforms/iseries/naca.h @@ -0,0 +1,24 @@ +#ifndef _PLATFORMS_ISERIES_NACA_H +#define _PLATFORMS_ISERIES_NACA_H + +/* + * c 2001 PPC 64 Team, IBM Corp + * + * 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 + +struct naca_struct { + /* Kernel only data - undefined for user space */ + void *xItVpdAreas; /* VPD Data 0x00 */ + void *xRamDisk; /* iSeries ramdisk 0x08 */ + u64 xRamDiskSize; /* In pages 0x10 */ +}; + +extern struct naca_struct naca; + +#endif /* _PLATFORMS_ISERIES_NACA_H */ diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h index c68b9c3e5caf..66189fd2e32d 100644 --- a/arch/powerpc/platforms/iseries/release_data.h +++ b/arch/powerpc/platforms/iseries/release_data.h @@ -24,7 +24,7 @@ * address of the OS's NACA). */ #include -#include +#include "naca.h" /* * When we IPL a secondary partition, we will check if if the diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 06431e642533..7bc19a594cc6 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -54,6 +53,7 @@ #include #include +#include "naca.h" #include "setup.h" #include "irq.h" #include "vpd_areas.h" diff --git a/arch/ppc64/kernel/udbg_scc.c b/arch/ppc64/kernel/udbg_scc.c index c47fd6c63531..820c53551507 100644 --- a/arch/ppc64/kernel/udbg_scc.c +++ b/arch/ppc64/kernel/udbg_scc.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/include/asm-ppc64/naca.h b/include/asm-ppc64/naca.h deleted file mode 100644 index d2afe6447597..000000000000 --- a/include/asm-ppc64/naca.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _NACA_H -#define _NACA_H - -/* - * c 2001 PPC 64 Team, IBM Corp - * - * 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 - -struct naca_struct { - /* Kernel only data - undefined for user space */ - void *xItVpdAreas; /* VPD Data 0x00 */ - void *xRamDisk; /* iSeries ramdisk 0x08 */ - u64 xRamDiskSize; /* In pages 0x10 */ -}; - -extern struct naca_struct naca; - -#endif /* _NACA_H */ -- cgit v1.2.3 From 9dc2d0f55fb693ae6d50c8dd3d934fe3133ca183 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 2 Nov 2005 11:51:15 +0000 Subject: [ARM] Fix realview machine type for patch 3060/1 Realview was missed in this cleanup... Signed-off-by: Russell King --- include/asm-arm/arch-realview/memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-realview/memory.h b/include/asm-arm/arch-realview/memory.h index 99667d5cc617..ed370abb638f 100644 --- a/include/asm-arm/arch-realview/memory.h +++ b/include/asm-arm/arch-realview/memory.h @@ -23,7 +23,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET (0x00000000UL) +#define PHYS_OFFSET UL(0x00000000) /* * Virtual view <-> DMA view memory address translations -- cgit v1.2.3 From bfca94590bfd3dcd958c542d2fb6406518150fee Mon Sep 17 00:00:00 2001 From: John Bowler Date: Wed, 2 Nov 2005 11:55:12 +0000 Subject: [ARM] 3083/1: include/asm-arm/arch-ixp4xx/io.h: eliminate warnings for pointer passed to integral function argument Patch from John Bowler Fix for a compiler warning, this wasn't apparent in 2.6.12, I believe the compiler options have been changed (somewhere) so that passing a (void*) to a (u32) argument is now warned. This accounts for the majority of the warnings in my builds of the 2.6.14 kernel for NSLU2. The patch changes pointer parameters declared as u32 to be declared as either, for read parameters: const volatile void __iomem * and for write parameters: volatile void __iomem * Signed-off-by: John Bowler Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- include/asm-arm/arch-ixp4xx/io.h | 74 ++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 34 deletions(-) (limited to 'include') diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h index 80d05ecad2f0..688f7f90d93e 100644 --- a/include/asm-arm/arch-ixp4xx/io.h +++ b/include/asm-arm/arch-ixp4xx/io.h @@ -80,9 +80,9 @@ __ixp4xx_iounmap(void __iomem *addr) #define __arch_ioremap(a, s, f, x) __ixp4xx_ioremap(a, s, f, x) #define __arch_iounmap(a) __ixp4xx_iounmap(a) -#define writeb(p, v) __ixp4xx_writeb(p, v) -#define writew(p, v) __ixp4xx_writew(p, v) -#define writel(p, v) __ixp4xx_writel(p, v) +#define writeb(v, p) __ixp4xx_writeb(v, p) +#define writew(v, p) __ixp4xx_writew(v, p) +#define writel(v, p) __ixp4xx_writel(v, p) #define writesb(p, v, l) __ixp4xx_writesb(p, v, l) #define writesw(p, v, l) __ixp4xx_writesw(p, v, l) @@ -97,8 +97,9 @@ __ixp4xx_iounmap(void __iomem *addr) #define readsl(p, v, l) __ixp4xx_readsl(p, v, l) static inline void -__ixp4xx_writeb(u8 value, u32 addr) +__ixp4xx_writeb(u8 value, volatile void __iomem *p) { + u32 addr = (u32)p; u32 n, byte_enables, data; if (addr >= VMALLOC_START) { @@ -113,15 +114,16 @@ __ixp4xx_writeb(u8 value, u32 addr) } static inline void -__ixp4xx_writesb(u32 bus_addr, const u8 *vaddr, int count) +__ixp4xx_writesb(volatile void __iomem *bus_addr, const u8 *vaddr, int count) { while (count--) writeb(*vaddr++, bus_addr); } static inline void -__ixp4xx_writew(u16 value, u32 addr) +__ixp4xx_writew(u16 value, volatile void __iomem *p) { + u32 addr = (u32)p; u32 n, byte_enables, data; if (addr >= VMALLOC_START) { @@ -136,15 +138,16 @@ __ixp4xx_writew(u16 value, u32 addr) } static inline void -__ixp4xx_writesw(u32 bus_addr, const u16 *vaddr, int count) +__ixp4xx_writesw(volatile void __iomem *bus_addr, const u16 *vaddr, int count) { while (count--) writew(*vaddr++, bus_addr); } static inline void -__ixp4xx_writel(u32 value, u32 addr) +__ixp4xx_writel(u32 value, volatile void __iomem *p) { + u32 addr = (u32)p; if (addr >= VMALLOC_START) { __raw_writel(value, addr); return; @@ -154,15 +157,16 @@ __ixp4xx_writel(u32 value, u32 addr) } static inline void -__ixp4xx_writesl(u32 bus_addr, const u32 *vaddr, int count) +__ixp4xx_writesl(volatile void __iomem *bus_addr, const u32 *vaddr, int count) { while (count--) writel(*vaddr++, bus_addr); } static inline unsigned char -__ixp4xx_readb(u32 addr) +__ixp4xx_readb(const volatile void __iomem *p) { + u32 addr = (u32)p; u32 n, byte_enables, data; if (addr >= VMALLOC_START) @@ -177,15 +181,16 @@ __ixp4xx_readb(u32 addr) } static inline void -__ixp4xx_readsb(u32 bus_addr, u8 *vaddr, u32 count) +__ixp4xx_readsb(const volatile void __iomem *bus_addr, u8 *vaddr, u32 count) { while (count--) *vaddr++ = readb(bus_addr); } static inline unsigned short -__ixp4xx_readw(u32 addr) +__ixp4xx_readw(const volatile void __iomem *p) { + u32 addr = (u32)p; u32 n, byte_enables, data; if (addr >= VMALLOC_START) @@ -200,15 +205,16 @@ __ixp4xx_readw(u32 addr) } static inline void -__ixp4xx_readsw(u32 bus_addr, u16 *vaddr, u32 count) +__ixp4xx_readsw(const volatile void __iomem *bus_addr, u16 *vaddr, u32 count) { while (count--) *vaddr++ = readw(bus_addr); } static inline unsigned long -__ixp4xx_readl(u32 addr) +__ixp4xx_readl(const volatile void __iomem *p) { + u32 addr = (u32)p; u32 data; if (addr >= VMALLOC_START) @@ -221,7 +227,7 @@ __ixp4xx_readl(u32 addr) } static inline void -__ixp4xx_readsl(u32 bus_addr, u32 *vaddr, u32 count) +__ixp4xx_readsl(const volatile void __iomem *bus_addr, u32 *vaddr, u32 count) { while (count--) *vaddr++ = readl(bus_addr); @@ -239,7 +245,7 @@ __ixp4xx_readsl(u32 bus_addr, u32 *vaddr, u32 count) eth_copy_and_sum((s),__mem_pci(c),(l),(b)) static inline int -check_signature(unsigned long bus_addr, const unsigned char *signature, +check_signature(const unsigned char __iomem *bus_addr, const unsigned char *signature, int length) { int retval = 0; @@ -389,7 +395,7 @@ __ixp4xx_insl(u32 io_addr, u32 *vaddr, u32 count) #define __is_io_address(p) (((unsigned long)p >= PIO_OFFSET) && \ ((unsigned long)p <= (PIO_MASK + PIO_OFFSET))) static inline unsigned int -__ixp4xx_ioread8(void __iomem *addr) +__ixp4xx_ioread8(const void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) @@ -398,12 +404,12 @@ __ixp4xx_ioread8(void __iomem *addr) #ifndef CONFIG_IXP4XX_INDIRECT_PCI return (unsigned int)__raw_readb(port); #else - return (unsigned int)__ixp4xx_readb(port); + return (unsigned int)__ixp4xx_readb(addr); #endif } static inline void -__ixp4xx_ioread8_rep(void __iomem *addr, void *vaddr, u32 count) +__ixp4xx_ioread8_rep(const void __iomem *addr, void *vaddr, u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) @@ -412,12 +418,12 @@ __ixp4xx_ioread8_rep(void __iomem *addr, void *vaddr, u32 count) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_readsb(addr, vaddr, count); #else - __ixp4xx_readsb(port, vaddr, count); + __ixp4xx_readsb(addr, vaddr, count); #endif } static inline unsigned int -__ixp4xx_ioread16(void __iomem *addr) +__ixp4xx_ioread16(const void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) @@ -426,12 +432,12 @@ __ixp4xx_ioread16(void __iomem *addr) #ifndef CONFIG_IXP4XX_INDIRECT_PCI return le16_to_cpu(__raw_readw((u32)port)); #else - return (unsigned int)__ixp4xx_readw((u32)port); + return (unsigned int)__ixp4xx_readw(addr); #endif } static inline void -__ixp4xx_ioread16_rep(void __iomem *addr, void *vaddr, u32 count) +__ixp4xx_ioread16_rep(const void __iomem *addr, void *vaddr, u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) @@ -440,12 +446,12 @@ __ixp4xx_ioread16_rep(void __iomem *addr, void *vaddr, u32 count) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_readsw(addr, vaddr, count); #else - __ixp4xx_readsw(port, vaddr, count); + __ixp4xx_readsw(addr, vaddr, count); #endif } static inline unsigned int -__ixp4xx_ioread32(void __iomem *addr) +__ixp4xx_ioread32(const void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) @@ -454,13 +460,13 @@ __ixp4xx_ioread32(void __iomem *addr) #ifndef CONFIG_IXP4XX_INDIRECT_PCI return le32_to_cpu(__raw_readl((u32)port)); #else - return (unsigned int)__ixp4xx_readl((u32)port); + return (unsigned int)__ixp4xx_readl(addr); #endif } } static inline void -__ixp4xx_ioread32_rep(void __iomem *addr, void *vaddr, u32 count) +__ixp4xx_ioread32_rep(const void __iomem *addr, void *vaddr, u32 count) { unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) @@ -469,7 +475,7 @@ __ixp4xx_ioread32_rep(void __iomem *addr, void *vaddr, u32 count) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_readsl(addr, vaddr, count); #else - __ixp4xx_readsl(port, vaddr, count); + __ixp4xx_readsl(addr, vaddr, count); #endif } @@ -483,7 +489,7 @@ __ixp4xx_iowrite8(u8 value, void __iomem *addr) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writeb(value, port); #else - __ixp4xx_writeb(value, port); + __ixp4xx_writeb(value, addr); #endif } @@ -497,7 +503,7 @@ __ixp4xx_iowrite8_rep(void __iomem *addr, const void *vaddr, u32 count) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writesb(addr, vaddr, count); #else - __ixp4xx_writesb(port, vaddr, count); + __ixp4xx_writesb(addr, vaddr, count); #endif } @@ -511,7 +517,7 @@ __ixp4xx_iowrite16(u16 value, void __iomem *addr) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writew(cpu_to_le16(value), addr); #else - __ixp4xx_writew(value, port); + __ixp4xx_writew(value, addr); #endif } @@ -525,7 +531,7 @@ __ixp4xx_iowrite16_rep(void __iomem *addr, const void *vaddr, u32 count) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writesw(addr, vaddr, count); #else - __ixp4xx_writesw(port, vaddr, count); + __ixp4xx_writesw(addr, vaddr, count); #endif } @@ -539,7 +545,7 @@ __ixp4xx_iowrite32(u32 value, void __iomem *addr) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writel(cpu_to_le32(value), port); #else - __ixp4xx_writel(value, port); + __ixp4xx_writel(value, addr); #endif } @@ -553,7 +559,7 @@ __ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count) #ifndef CONFIG_IXP4XX_INDIRECT_PCI __raw_writesl(addr, vaddr, count); #else - __ixp4xx_writesl(port, vaddr, count); + __ixp4xx_writesl(addr, vaddr, count); #endif } -- cgit v1.2.3 From 7e86df273292b3a88c14b9aed1006cddac2b4c23 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 2 Nov 2005 15:09:31 +0000 Subject: [ARM] Fix ARM rwlock implementations fb1c8f93d869b34cacb8b8932e2b83d96a19d720 broke the ARM rwlock code since it only partially updated the rwlock implementation. Properly update it. Signed-off-by: Russell King --- include/asm-arm/spinlock.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h index cb4906b45555..6ed4f916b166 100644 --- a/include/asm-arm/spinlock.h +++ b/include/asm-arm/spinlock.h @@ -80,7 +80,7 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock) */ #define rwlock_is_locked(x) (*((volatile unsigned int *)(x)) != 0) -static inline void __raw_write_lock(rwlock_t *rw) +static inline void __raw_write_lock(raw_rwlock_t *rw) { unsigned long tmp; @@ -97,7 +97,7 @@ static inline void __raw_write_lock(rwlock_t *rw) smp_mb(); } -static inline int __raw_write_trylock(rwlock_t *rw) +static inline int __raw_write_trylock(raw_rwlock_t *rw) { unsigned long tmp; @@ -157,7 +157,7 @@ static inline void __raw_read_lock(raw_rwlock_t *rw) smp_mb(); } -static inline void __raw_read_unlock(rwlock_t *rw) +static inline void __raw_read_unlock(raw_rwlock_t *rw) { unsigned long tmp, tmp2; -- cgit v1.2.3 From 71f512e89704f5aa6fc0b97e4a719184080b8938 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 2 Nov 2005 21:51:40 +0000 Subject: [ARM SMP] Track CPU idle threads Track the idle thread task_struct for each CPU. Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 20 +++++++++++++------- include/asm-arm/cpu.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 826164945747..45877f5d5717 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -80,19 +80,23 @@ static DEFINE_SPINLOCK(smp_call_function_lock); int __cpuinit __cpu_up(unsigned int cpu) { - struct task_struct *idle; + struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); + struct task_struct *idle = ci->idle; pgd_t *pgd; pmd_t *pmd; int ret; /* - * Spawn a new process manually. Grab a pointer to - * its task struct so we can mess with it + * Spawn a new process manually, if not already done. + * Grab a pointer to its task struct so we can mess with it */ - idle = fork_idle(cpu); - if (IS_ERR(idle)) { - printk(KERN_ERR "CPU%u: fork() failed\n", cpu); - return PTR_ERR(idle); + if (!idle) { + idle = fork_idle(cpu); + if (IS_ERR(idle)) { + printk(KERN_ERR "CPU%u: fork() failed\n", cpu); + return PTR_ERR(idle); + } + ci->idle = idle; } /* @@ -236,6 +240,8 @@ void __init smp_prepare_boot_cpu(void) { unsigned int cpu = smp_processor_id(); + per_cpu(cpu_data, cpu).idle = current; + cpu_set(cpu, cpu_possible_map); cpu_set(cpu, cpu_present_map); cpu_set(cpu, cpu_online_map); diff --git a/include/asm-arm/cpu.h b/include/asm-arm/cpu.h index fcbdd40cb667..751bc7462074 100644 --- a/include/asm-arm/cpu.h +++ b/include/asm-arm/cpu.h @@ -16,6 +16,7 @@ struct cpuinfo_arm { struct cpu cpu; #ifdef CONFIG_SMP + struct task_struct *idle; unsigned int loops_per_jiffy; #endif }; -- cgit v1.2.3 From aef9ec39c47f0cece886ddd6b53c440321e0b2a6 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 2 Nov 2005 14:07:13 -0800 Subject: IB: Add SCSI RDMA Protocol (SRP) initiator Add an InfiniBand SCSI RDMA Protocol (SRP) initiator. This driver is used to talk talk to InfiniBand SRP targets (storage devices). Signed-off-by: Roland Dreier --- drivers/infiniband/Kconfig | 2 + drivers/infiniband/Makefile | 1 + drivers/infiniband/ulp/srp/Kbuild | 1 + drivers/infiniband/ulp/srp/Kconfig | 11 + drivers/infiniband/ulp/srp/ib_srp.c | 1700 +++++++++++++++++++++++++++++++++++ drivers/infiniband/ulp/srp/ib_srp.h | 150 ++++ include/scsi/srp.h | 226 +++++ 7 files changed, 2091 insertions(+) create mode 100644 drivers/infiniband/ulp/srp/Kbuild create mode 100644 drivers/infiniband/ulp/srp/Kconfig create mode 100644 drivers/infiniband/ulp/srp/ib_srp.c create mode 100644 drivers/infiniband/ulp/srp/ib_srp.h create mode 100644 include/scsi/srp.h (limited to 'include') diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index 325d502e25cd..bdf0891a92dd 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -33,4 +33,6 @@ source "drivers/infiniband/hw/mthca/Kconfig" source "drivers/infiniband/ulp/ipoib/Kconfig" +source "drivers/infiniband/ulp/srp/Kconfig" + endmenu diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile index d256cf798218..a43fb34cca94 100644 --- a/drivers/infiniband/Makefile +++ b/drivers/infiniband/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_INFINIBAND) += core/ obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ +obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ diff --git a/drivers/infiniband/ulp/srp/Kbuild b/drivers/infiniband/ulp/srp/Kbuild new file mode 100644 index 000000000000..a16c73c667cb --- /dev/null +++ b/drivers/infiniband/ulp/srp/Kbuild @@ -0,0 +1 @@ +obj-$(CONFIG_INFINIBAND_SRP) += ib_srp.o diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig new file mode 100644 index 000000000000..8fe3be4e9910 --- /dev/null +++ b/drivers/infiniband/ulp/srp/Kconfig @@ -0,0 +1,11 @@ +config INFINIBAND_SRP + tristate "InfiniBand SCSI RDMA Protocol" + depends on INFINIBAND && SCSI + ---help--- + Support for the SCSI RDMA Protocol over InfiniBand. This + allows you to access storage devices that speak SRP over + InfiniBand. + + The SRP protocol is defined by the INCITS T10 technical + committee. See . + diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c new file mode 100644 index 000000000000..2687e34aa5bc --- /dev/null +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -0,0 +1,1700 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: ib_srp.c 3932 2005-11-01 17:19:29Z roland $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "ib_srp.h" + +#define DRV_NAME "ib_srp" +#define PFX DRV_NAME ": " +#define DRV_VERSION "0.2" +#define DRV_RELDATE "November 1, 2005" + +MODULE_AUTHOR("Roland Dreier"); +MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator " + "v" DRV_VERSION " (" DRV_RELDATE ")"); +MODULE_LICENSE("Dual BSD/GPL"); + +static int topspin_workarounds = 1; + +module_param(topspin_workarounds, int, 0444); +MODULE_PARM_DESC(topspin_workarounds, + "Enable workarounds for Topspin/Cisco SRP target bugs if != 0"); + +static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad }; + +static void srp_add_one(struct ib_device *device); +static void srp_remove_one(struct ib_device *device); +static void srp_completion(struct ib_cq *cq, void *target_ptr); +static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event); + +static struct ib_client srp_client = { + .name = "srp", + .add = srp_add_one, + .remove = srp_remove_one +}; + +static inline struct srp_target_port *host_to_target(struct Scsi_Host *host) +{ + return (struct srp_target_port *) host->hostdata; +} + +static const char *srp_target_info(struct Scsi_Host *host) +{ + return host_to_target(host)->target_name; +} + +static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size, + gfp_t gfp_mask, + enum dma_data_direction direction) +{ + struct srp_iu *iu; + + iu = kmalloc(sizeof *iu, gfp_mask); + if (!iu) + goto out; + + iu->buf = kzalloc(size, gfp_mask); + if (!iu->buf) + goto out_free_iu; + + iu->dma = dma_map_single(host->dev->dma_device, iu->buf, size, direction); + if (dma_mapping_error(iu->dma)) + goto out_free_buf; + + iu->size = size; + iu->direction = direction; + + return iu; + +out_free_buf: + kfree(iu->buf); +out_free_iu: + kfree(iu); +out: + return NULL; +} + +static void srp_free_iu(struct srp_host *host, struct srp_iu *iu) +{ + if (!iu) + return; + + dma_unmap_single(host->dev->dma_device, iu->dma, iu->size, iu->direction); + kfree(iu->buf); + kfree(iu); +} + +static void srp_qp_event(struct ib_event *event, void *context) +{ + printk(KERN_ERR PFX "QP event %d\n", event->event); +} + +static int srp_init_qp(struct srp_target_port *target, + struct ib_qp *qp) +{ + struct ib_qp_attr *attr; + int ret; + + attr = kmalloc(sizeof *attr, GFP_KERNEL); + if (!attr) + return -ENOMEM; + + ret = ib_find_cached_pkey(target->srp_host->dev, + target->srp_host->port, + be16_to_cpu(target->path.pkey), + &attr->pkey_index); + if (ret) + goto out; + + attr->qp_state = IB_QPS_INIT; + attr->qp_access_flags = (IB_ACCESS_REMOTE_READ | + IB_ACCESS_REMOTE_WRITE); + attr->port_num = target->srp_host->port; + + ret = ib_modify_qp(qp, attr, + IB_QP_STATE | + IB_QP_PKEY_INDEX | + IB_QP_ACCESS_FLAGS | + IB_QP_PORT); + +out: + kfree(attr); + return ret; +} + +static int srp_create_target_ib(struct srp_target_port *target) +{ + struct ib_qp_init_attr *init_attr; + int ret; + + init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); + if (!init_attr) + return -ENOMEM; + + target->cq = ib_create_cq(target->srp_host->dev, srp_completion, + NULL, target, SRP_CQ_SIZE); + if (IS_ERR(target->cq)) { + ret = PTR_ERR(target->cq); + goto out; + } + + ib_req_notify_cq(target->cq, IB_CQ_NEXT_COMP); + + init_attr->event_handler = srp_qp_event; + init_attr->cap.max_send_wr = SRP_SQ_SIZE; + init_attr->cap.max_recv_wr = SRP_RQ_SIZE; + init_attr->cap.max_recv_sge = 1; + init_attr->cap.max_send_sge = 1; + init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; + init_attr->qp_type = IB_QPT_RC; + init_attr->send_cq = target->cq; + init_attr->recv_cq = target->cq; + + target->qp = ib_create_qp(target->srp_host->pd, init_attr); + if (IS_ERR(target->qp)) { + ret = PTR_ERR(target->qp); + ib_destroy_cq(target->cq); + goto out; + } + + ret = srp_init_qp(target, target->qp); + if (ret) { + ib_destroy_qp(target->qp); + ib_destroy_cq(target->cq); + goto out; + } + +out: + kfree(init_attr); + return ret; +} + +static void srp_free_target_ib(struct srp_target_port *target) +{ + int i; + + ib_destroy_qp(target->qp); + ib_destroy_cq(target->cq); + + for (i = 0; i < SRP_RQ_SIZE; ++i) + srp_free_iu(target->srp_host, target->rx_ring[i]); + for (i = 0; i < SRP_SQ_SIZE + 1; ++i) + srp_free_iu(target->srp_host, target->tx_ring[i]); +} + +static void srp_path_rec_completion(int status, + struct ib_sa_path_rec *pathrec, + void *target_ptr) +{ + struct srp_target_port *target = target_ptr; + + target->status = status; + if (status) + printk(KERN_ERR PFX "Got failed path rec status %d\n", status); + else + target->path = *pathrec; + complete(&target->done); +} + +static int srp_lookup_path(struct srp_target_port *target) +{ + target->path.numb_path = 1; + + init_completion(&target->done); + + target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev, + target->srp_host->port, + &target->path, + IB_SA_PATH_REC_DGID | + IB_SA_PATH_REC_SGID | + IB_SA_PATH_REC_NUMB_PATH | + IB_SA_PATH_REC_PKEY, + SRP_PATH_REC_TIMEOUT_MS, + GFP_KERNEL, + srp_path_rec_completion, + target, &target->path_query); + if (target->path_query_id < 0) + return target->path_query_id; + + wait_for_completion(&target->done); + + if (target->status < 0) + printk(KERN_WARNING PFX "Path record query failed\n"); + + return target->status; +} + +static int srp_send_req(struct srp_target_port *target) +{ + struct { + struct ib_cm_req_param param; + struct srp_login_req priv; + } *req = NULL; + int status; + + req = kzalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->param.primary_path = &target->path; + req->param.alternate_path = NULL; + req->param.service_id = target->service_id; + req->param.qp_num = target->qp->qp_num; + req->param.qp_type = target->qp->qp_type; + req->param.private_data = &req->priv; + req->param.private_data_len = sizeof req->priv; + req->param.flow_control = 1; + + get_random_bytes(&req->param.starting_psn, 4); + req->param.starting_psn &= 0xffffff; + + /* + * Pick some arbitrary defaults here; we could make these + * module parameters if anyone cared about setting them. + */ + req->param.responder_resources = 4; + req->param.remote_cm_response_timeout = 20; + req->param.local_cm_response_timeout = 20; + req->param.retry_count = 7; + req->param.rnr_retry_count = 7; + req->param.max_cm_retries = 15; + + req->priv.opcode = SRP_LOGIN_REQ; + req->priv.tag = 0; + req->priv.req_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN); + req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | + SRP_BUF_FORMAT_INDIRECT); + memcpy(req->priv.initiator_port_id, target->srp_host->initiator_port_id, 16); + /* + * Topspin/Cisco SRP targets will reject our login unless we + * zero out the first 8 bytes of our initiator port ID. The + * second 8 bytes must be our local node GUID, but we always + * use that anyway. + */ + if (topspin_workarounds && !memcmp(&target->ioc_guid, topspin_oui, 3)) { + printk(KERN_DEBUG PFX "Topspin/Cisco initiator port ID workaround " + "activated for target GUID %016llx\n", + (unsigned long long) be64_to_cpu(target->ioc_guid)); + memset(req->priv.initiator_port_id, 0, 8); + } + memcpy(req->priv.target_port_id, &target->id_ext, 8); + memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); + + status = ib_send_cm_req(target->cm_id, &req->param); + + kfree(req); + + return status; +} + +static void srp_disconnect_target(struct srp_target_port *target) +{ + /* XXX should send SRP_I_LOGOUT request */ + + init_completion(&target->done); + ib_send_cm_dreq(target->cm_id, NULL, 0); + wait_for_completion(&target->done); +} + +static void srp_remove_work(void *target_ptr) +{ + struct srp_target_port *target = target_ptr; + + spin_lock_irq(target->scsi_host->host_lock); + if (target->state != SRP_TARGET_DEAD) { + spin_unlock_irq(target->scsi_host->host_lock); + scsi_host_put(target->scsi_host); + return; + } + target->state = SRP_TARGET_REMOVED; + spin_unlock_irq(target->scsi_host->host_lock); + + down(&target->srp_host->target_mutex); + list_del(&target->list); + up(&target->srp_host->target_mutex); + + scsi_remove_host(target->scsi_host); + ib_destroy_cm_id(target->cm_id); + srp_free_target_ib(target); + scsi_host_put(target->scsi_host); + /* And another put to really free the target port... */ + scsi_host_put(target->scsi_host); +} + +static int srp_connect_target(struct srp_target_port *target) +{ + int ret; + + ret = srp_lookup_path(target); + if (ret) + return ret; + + while (1) { + init_completion(&target->done); + ret = srp_send_req(target); + if (ret) + return ret; + wait_for_completion(&target->done); + + /* + * The CM event handling code will set status to + * SRP_PORT_REDIRECT if we get a port redirect REJ + * back, or SRP_DLID_REDIRECT if we get a lid/qp + * redirect REJ back. + */ + switch (target->status) { + case 0: + return 0; + + case SRP_PORT_REDIRECT: + ret = srp_lookup_path(target); + if (ret) + return ret; + break; + + case SRP_DLID_REDIRECT: + break; + + default: + return target->status; + } + } +} + +static int srp_reconnect_target(struct srp_target_port *target) +{ + struct ib_cm_id *new_cm_id; + struct ib_qp_attr qp_attr; + struct srp_request *req; + struct ib_wc wc; + int ret; + int i; + + spin_lock_irq(target->scsi_host->host_lock); + if (target->state != SRP_TARGET_LIVE) { + spin_unlock_irq(target->scsi_host->host_lock); + return -EAGAIN; + } + target->state = SRP_TARGET_CONNECTING; + spin_unlock_irq(target->scsi_host->host_lock); + + srp_disconnect_target(target); + /* + * Now get a new local CM ID so that we avoid confusing the + * target in case things are really fouled up. + */ + new_cm_id = ib_create_cm_id(target->srp_host->dev, + srp_cm_handler, target); + if (IS_ERR(new_cm_id)) { + ret = PTR_ERR(new_cm_id); + goto err; + } + ib_destroy_cm_id(target->cm_id); + target->cm_id = new_cm_id; + + qp_attr.qp_state = IB_QPS_RESET; + ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE); + if (ret) + goto err; + + ret = srp_init_qp(target, target->qp); + if (ret) + goto err; + + while (ib_poll_cq(target->cq, 1, &wc) > 0) + ; /* nothing */ + + list_for_each_entry(req, &target->req_queue, list) { + req->scmnd->result = DID_RESET << 16; + req->scmnd->scsi_done(req->scmnd); + } + + target->rx_head = 0; + target->tx_head = 0; + target->tx_tail = 0; + target->req_head = 0; + for (i = 0; i < SRP_SQ_SIZE - 1; ++i) + target->req_ring[i].next = i + 1; + target->req_ring[SRP_SQ_SIZE - 1].next = -1; + INIT_LIST_HEAD(&target->req_queue); + + ret = srp_connect_target(target); + if (ret) + goto err; + + spin_lock_irq(target->scsi_host->host_lock); + if (target->state == SRP_TARGET_CONNECTING) { + ret = 0; + target->state = SRP_TARGET_LIVE; + } else + ret = -EAGAIN; + spin_unlock_irq(target->scsi_host->host_lock); + + return ret; + +err: + printk(KERN_ERR PFX "reconnect failed (%d), removing target port.\n", ret); + + /* + * We couldn't reconnect, so kill our target port off. + * However, we have to defer the real removal because we might + * be in the context of the SCSI error handler now, which + * would deadlock if we call scsi_remove_host(). + */ + spin_lock_irq(target->scsi_host->host_lock); + if (target->state == SRP_TARGET_CONNECTING) { + target->state = SRP_TARGET_DEAD; + INIT_WORK(&target->work, srp_remove_work, target); + schedule_work(&target->work); + } + spin_unlock_irq(target->scsi_host->host_lock); + + return ret; +} + +static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, + struct srp_request *req) +{ + struct srp_cmd *cmd = req->cmd->buf; + int len; + u8 fmt; + + if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE) + return sizeof (struct srp_cmd); + + if (scmnd->sc_data_direction != DMA_FROM_DEVICE && + scmnd->sc_data_direction != DMA_TO_DEVICE) { + printk(KERN_WARNING PFX "Unhandled data direction %d\n", + scmnd->sc_data_direction); + return -EINVAL; + } + + if (scmnd->use_sg) { + struct scatterlist *scat = scmnd->request_buffer; + int n; + int i; + + n = dma_map_sg(target->srp_host->dev->dma_device, + scat, scmnd->use_sg, scmnd->sc_data_direction); + + if (n == 1) { + struct srp_direct_buf *buf = (void *) cmd->add_data; + + fmt = SRP_DATA_DESC_DIRECT; + + buf->va = cpu_to_be64(sg_dma_address(scat)); + buf->key = cpu_to_be32(target->srp_host->mr->rkey); + buf->len = cpu_to_be32(sg_dma_len(scat)); + + len = sizeof (struct srp_cmd) + + sizeof (struct srp_direct_buf); + } else { + struct srp_indirect_buf *buf = (void *) cmd->add_data; + u32 datalen = 0; + + fmt = SRP_DATA_DESC_INDIRECT; + + if (scmnd->sc_data_direction == DMA_TO_DEVICE) + cmd->data_out_desc_cnt = n; + else + cmd->data_in_desc_cnt = n; + + buf->table_desc.va = cpu_to_be64(req->cmd->dma + + sizeof *cmd + + sizeof *buf); + buf->table_desc.key = + cpu_to_be32(target->srp_host->mr->rkey); + buf->table_desc.len = + cpu_to_be32(n * sizeof (struct srp_direct_buf)); + + for (i = 0; i < n; ++i) { + buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i])); + buf->desc_list[i].key = + cpu_to_be32(target->srp_host->mr->rkey); + buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i])); + + datalen += sg_dma_len(&scat[i]); + } + + buf->len = cpu_to_be32(datalen); + + len = sizeof (struct srp_cmd) + + sizeof (struct srp_indirect_buf) + + n * sizeof (struct srp_direct_buf); + } + } else { + struct srp_direct_buf *buf = (void *) cmd->add_data; + dma_addr_t dma; + + dma = dma_map_single(target->srp_host->dev->dma_device, + scmnd->request_buffer, scmnd->request_bufflen, + scmnd->sc_data_direction); + if (dma_mapping_error(dma)) { + printk(KERN_WARNING PFX "unable to map %p/%d (dir %d)\n", + scmnd->request_buffer, (int) scmnd->request_bufflen, + scmnd->sc_data_direction); + return -EINVAL; + } + + pci_unmap_addr_set(req, direct_mapping, dma); + + buf->va = cpu_to_be64(dma); + buf->key = cpu_to_be32(target->srp_host->mr->rkey); + buf->len = cpu_to_be32(scmnd->request_bufflen); + + fmt = SRP_DATA_DESC_DIRECT; + + len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf); + } + + if (scmnd->sc_data_direction == DMA_TO_DEVICE) + cmd->buf_fmt = fmt << 4; + else + cmd->buf_fmt = fmt; + + + return len; +} + +static void srp_unmap_data(struct scsi_cmnd *scmnd, + struct srp_target_port *target, + struct srp_request *req) +{ + if (!scmnd->request_buffer || + (scmnd->sc_data_direction != DMA_TO_DEVICE && + scmnd->sc_data_direction != DMA_FROM_DEVICE)) + return; + + if (scmnd->use_sg) + dma_unmap_sg(target->srp_host->dev->dma_device, + (struct scatterlist *) scmnd->request_buffer, + scmnd->use_sg, scmnd->sc_data_direction); + else + dma_unmap_single(target->srp_host->dev->dma_device, + pci_unmap_addr(req, direct_mapping), + scmnd->request_bufflen, + scmnd->sc_data_direction); +} + +static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) +{ + struct srp_request *req; + struct scsi_cmnd *scmnd; + unsigned long flags; + s32 delta; + + delta = (s32) be32_to_cpu(rsp->req_lim_delta); + + spin_lock_irqsave(target->scsi_host->host_lock, flags); + + target->req_lim += delta; + + req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT]; + + if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) { + if (be32_to_cpu(rsp->resp_data_len) < 4) + req->tsk_status = -1; + else + req->tsk_status = rsp->data[3]; + complete(&req->done); + } else { + scmnd = req->scmnd; + if (!scmnd) + printk(KERN_ERR "Null scmnd for RSP w/tag %016llx\n", + (unsigned long long) rsp->tag); + scmnd->result = rsp->status; + + if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { + memcpy(scmnd->sense_buffer, rsp->data + + be32_to_cpu(rsp->resp_data_len), + min_t(int, be32_to_cpu(rsp->sense_data_len), + SCSI_SENSE_BUFFERSIZE)); + } + + if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER)) + scmnd->resid = be32_to_cpu(rsp->data_out_res_cnt); + else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) + scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt); + + srp_unmap_data(scmnd, target, req); + + if (!req->tsk_mgmt) { + req->scmnd = NULL; + scmnd->host_scribble = (void *) -1L; + scmnd->scsi_done(scmnd); + + list_del(&req->list); + req->next = target->req_head; + target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT; + } else + req->cmd_done = 1; + } + + spin_unlock_irqrestore(target->scsi_host->host_lock, flags); +} + +static void srp_reconnect_work(void *target_ptr) +{ + struct srp_target_port *target = target_ptr; + + srp_reconnect_target(target); +} + +static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) +{ + struct srp_iu *iu; + u8 opcode; + + iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV]; + + dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma, + target->max_ti_iu_len, DMA_FROM_DEVICE); + + opcode = *(u8 *) iu->buf; + + if (0) { + int i; + + printk(KERN_ERR PFX "recv completion, opcode 0x%02x\n", opcode); + + for (i = 0; i < wc->byte_len; ++i) { + if (i % 8 == 0) + printk(KERN_ERR " [%02x] ", i); + printk(" %02x", ((u8 *) iu->buf)[i]); + if ((i + 1) % 8 == 0) + printk("\n"); + } + + if (wc->byte_len % 8) + printk("\n"); + } + + switch (opcode) { + case SRP_RSP: + srp_process_rsp(target, iu->buf); + break; + + case SRP_T_LOGOUT: + /* XXX Handle target logout */ + printk(KERN_WARNING PFX "Got target logout request\n"); + break; + + default: + printk(KERN_WARNING PFX "Unhandled SRP opcode 0x%02x\n", opcode); + break; + } + + dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma, + target->max_ti_iu_len, DMA_FROM_DEVICE); +} + +static void srp_completion(struct ib_cq *cq, void *target_ptr) +{ + struct srp_target_port *target = target_ptr; + struct ib_wc wc; + unsigned long flags; + + ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); + while (ib_poll_cq(cq, 1, &wc) > 0) { + if (wc.status) { + printk(KERN_ERR PFX "failed %s status %d\n", + wc.wr_id & SRP_OP_RECV ? "receive" : "send", + wc.status); + spin_lock_irqsave(target->scsi_host->host_lock, flags); + if (target->state == SRP_TARGET_LIVE) + schedule_work(&target->work); + spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + break; + } + + if (wc.wr_id & SRP_OP_RECV) + srp_handle_recv(target, &wc); + else + ++target->tx_tail; + } +} + +static int __srp_post_recv(struct srp_target_port *target) +{ + struct srp_iu *iu; + struct ib_sge list; + struct ib_recv_wr wr, *bad_wr; + unsigned int next; + int ret; + + next = target->rx_head & (SRP_RQ_SIZE - 1); + wr.wr_id = next | SRP_OP_RECV; + iu = target->rx_ring[next]; + + list.addr = iu->dma; + list.length = iu->size; + list.lkey = target->srp_host->mr->lkey; + + wr.next = NULL; + wr.sg_list = &list; + wr.num_sge = 1; + + ret = ib_post_recv(target->qp, &wr, &bad_wr); + if (!ret) + ++target->rx_head; + + return ret; +} + +static int srp_post_recv(struct srp_target_port *target) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(target->scsi_host->host_lock, flags); + ret = __srp_post_recv(target); + spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + + return ret; +} + +/* + * Must be called with target->scsi_host->host_lock held to protect + * req_lim and tx_head. + */ +static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target) +{ + if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE) + return NULL; + + return target->tx_ring[target->tx_head & SRP_SQ_SIZE]; +} + +/* + * Must be called with target->scsi_host->host_lock held to protect + * req_lim and tx_head. + */ +static int __srp_post_send(struct srp_target_port *target, + struct srp_iu *iu, int len) +{ + struct ib_sge list; + struct ib_send_wr wr, *bad_wr; + int ret = 0; + + if (target->req_lim < 1) { + printk(KERN_ERR PFX "Target has req_lim %d\n", target->req_lim); + return -EAGAIN; + } + + list.addr = iu->dma; + list.length = len; + list.lkey = target->srp_host->mr->lkey; + + wr.next = NULL; + wr.wr_id = target->tx_head & SRP_SQ_SIZE; + wr.sg_list = &list; + wr.num_sge = 1; + wr.opcode = IB_WR_SEND; + wr.send_flags = IB_SEND_SIGNALED; + + ret = ib_post_send(target->qp, &wr, &bad_wr); + + if (!ret) { + ++target->tx_head; + --target->req_lim; + } + + return ret; +} + +static int srp_queuecommand(struct scsi_cmnd *scmnd, + void (*done)(struct scsi_cmnd *)) +{ + struct srp_target_port *target = host_to_target(scmnd->device->host); + struct srp_request *req; + struct srp_iu *iu; + struct srp_cmd *cmd; + long req_index; + int len; + + if (target->state == SRP_TARGET_CONNECTING) + goto err; + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) { + scmnd->result = DID_BAD_TARGET << 16; + done(scmnd); + return 0; + } + + iu = __srp_get_tx_iu(target); + if (!iu) + goto err; + + dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma, + SRP_MAX_IU_LEN, DMA_TO_DEVICE); + + req_index = target->req_head; + + scmnd->scsi_done = done; + scmnd->result = 0; + scmnd->host_scribble = (void *) req_index; + + cmd = iu->buf; + memset(cmd, 0, sizeof *cmd); + + cmd->opcode = SRP_CMD; + cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48); + cmd->tag = req_index; + memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len); + + req = &target->req_ring[req_index]; + + req->scmnd = scmnd; + req->cmd = iu; + req->cmd_done = 0; + req->tsk_mgmt = NULL; + + len = srp_map_data(scmnd, target, req); + if (len < 0) { + printk(KERN_ERR PFX "Failed to map data\n"); + goto err; + } + + if (__srp_post_recv(target)) { + printk(KERN_ERR PFX "Recv failed\n"); + goto err_unmap; + } + + dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma, + SRP_MAX_IU_LEN, DMA_TO_DEVICE); + + if (__srp_post_send(target, iu, len)) { + printk(KERN_ERR PFX "Send failed\n"); + goto err_unmap; + } + + target->req_head = req->next; + list_add_tail(&req->list, &target->req_queue); + + return 0; + +err_unmap: + srp_unmap_data(scmnd, target, req); + +err: + return SCSI_MLQUEUE_HOST_BUSY; +} + +static int srp_alloc_iu_bufs(struct srp_target_port *target) +{ + int i; + + for (i = 0; i < SRP_RQ_SIZE; ++i) { + target->rx_ring[i] = srp_alloc_iu(target->srp_host, + target->max_ti_iu_len, + GFP_KERNEL, DMA_FROM_DEVICE); + if (!target->rx_ring[i]) + goto err; + } + + for (i = 0; i < SRP_SQ_SIZE + 1; ++i) { + target->tx_ring[i] = srp_alloc_iu(target->srp_host, + SRP_MAX_IU_LEN, + GFP_KERNEL, DMA_TO_DEVICE); + if (!target->tx_ring[i]) + goto err; + } + + return 0; + +err: + for (i = 0; i < SRP_RQ_SIZE; ++i) { + srp_free_iu(target->srp_host, target->rx_ring[i]); + target->rx_ring[i] = NULL; + } + + for (i = 0; i < SRP_SQ_SIZE + 1; ++i) { + srp_free_iu(target->srp_host, target->tx_ring[i]); + target->tx_ring[i] = NULL; + } + + return -ENOMEM; +} + +static void srp_cm_rej_handler(struct ib_cm_id *cm_id, + struct ib_cm_event *event, + struct srp_target_port *target) +{ + struct ib_class_port_info *cpi; + int opcode; + + switch (event->param.rej_rcvd.reason) { + case IB_CM_REJ_PORT_CM_REDIRECT: + cpi = event->param.rej_rcvd.ari; + target->path.dlid = cpi->redirect_lid; + target->path.pkey = cpi->redirect_pkey; + cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff; + memcpy(target->path.dgid.raw, cpi->redirect_gid, 16); + + target->status = target->path.dlid ? + SRP_DLID_REDIRECT : SRP_PORT_REDIRECT; + break; + + case IB_CM_REJ_PORT_REDIRECT: + if (topspin_workarounds && + !memcmp(&target->ioc_guid, topspin_oui, 3)) { + /* + * Topspin/Cisco SRP gateways incorrectly send + * reject reason code 25 when they mean 24 + * (port redirect). + */ + memcpy(target->path.dgid.raw, + event->param.rej_rcvd.ari, 16); + + printk(KERN_DEBUG PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n", + (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix), + (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id)); + + target->status = SRP_PORT_REDIRECT; + } else { + printk(KERN_WARNING " REJ reason: IB_CM_REJ_PORT_REDIRECT\n"); + target->status = -ECONNRESET; + } + break; + + case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID: + printk(KERN_WARNING " REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n"); + target->status = -ECONNRESET; + break; + + case IB_CM_REJ_CONSUMER_DEFINED: + opcode = *(u8 *) event->private_data; + if (opcode == SRP_LOGIN_REJ) { + struct srp_login_rej *rej = event->private_data; + u32 reason = be32_to_cpu(rej->reason); + + if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE) + printk(KERN_WARNING PFX + "SRP_LOGIN_REJ: requested max_it_iu_len too large\n"); + else + printk(KERN_WARNING PFX + "SRP LOGIN REJECTED, reason 0x%08x\n", reason); + } else + printk(KERN_WARNING " REJ reason: IB_CM_REJ_CONSUMER_DEFINED," + " opcode 0x%02x\n", opcode); + target->status = -ECONNRESET; + break; + + default: + printk(KERN_WARNING " REJ reason 0x%x\n", + event->param.rej_rcvd.reason); + target->status = -ECONNRESET; + } +} + +static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) +{ + struct srp_target_port *target = cm_id->context; + struct ib_qp_attr *qp_attr = NULL; + int attr_mask = 0; + int comp = 0; + int opcode = 0; + + switch (event->event) { + case IB_CM_REQ_ERROR: + printk(KERN_DEBUG PFX "Sending CM REQ failed\n"); + comp = 1; + target->status = -ECONNRESET; + break; + + case IB_CM_REP_RECEIVED: + comp = 1; + opcode = *(u8 *) event->private_data; + + if (opcode == SRP_LOGIN_RSP) { + struct srp_login_rsp *rsp = event->private_data; + + target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len); + target->req_lim = be32_to_cpu(rsp->req_lim_delta); + + target->scsi_host->can_queue = min(target->req_lim, + target->scsi_host->can_queue); + } else { + printk(KERN_WARNING PFX "Unhandled RSP opcode %#x\n", opcode); + target->status = -ECONNRESET; + break; + } + + target->status = srp_alloc_iu_bufs(target); + if (target->status) + break; + + qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL); + if (!qp_attr) { + target->status = -ENOMEM; + break; + } + + qp_attr->qp_state = IB_QPS_RTR; + target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); + if (target->status) + break; + + target->status = ib_modify_qp(target->qp, qp_attr, attr_mask); + if (target->status) + break; + + target->status = srp_post_recv(target); + if (target->status) + break; + + qp_attr->qp_state = IB_QPS_RTS; + target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); + if (target->status) + break; + + target->status = ib_modify_qp(target->qp, qp_attr, attr_mask); + if (target->status) + break; + + target->status = ib_send_cm_rtu(cm_id, NULL, 0); + if (target->status) + break; + + break; + + case IB_CM_REJ_RECEIVED: + printk(KERN_DEBUG PFX "REJ received\n"); + comp = 1; + + srp_cm_rej_handler(cm_id, event, target); + break; + + case IB_CM_MRA_RECEIVED: + printk(KERN_ERR PFX "MRA received\n"); + break; + + case IB_CM_DREP_RECEIVED: + break; + + case IB_CM_TIMEWAIT_EXIT: + printk(KERN_ERR PFX "connection closed\n"); + + comp = 1; + target->status = 0; + break; + + default: + printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event); + break; + } + + if (comp) + complete(&target->done); + + kfree(qp_attr); + + return 0; +} + +static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func) +{ + struct srp_target_port *target = host_to_target(scmnd->device->host); + struct srp_request *req; + struct srp_iu *iu; + struct srp_tsk_mgmt *tsk_mgmt; + int req_index; + int ret = FAILED; + + spin_lock_irq(target->scsi_host->host_lock); + + if (scmnd->host_scribble == (void *) -1L) + goto out; + + req_index = (long) scmnd->host_scribble; + printk(KERN_ERR "Abort for req_index %d\n", req_index); + + req = &target->req_ring[req_index]; + init_completion(&req->done); + + iu = __srp_get_tx_iu(target); + if (!iu) + goto out; + + tsk_mgmt = iu->buf; + memset(tsk_mgmt, 0, sizeof *tsk_mgmt); + + tsk_mgmt->opcode = SRP_TSK_MGMT; + tsk_mgmt->lun = cpu_to_be64((u64) scmnd->device->lun << 48); + tsk_mgmt->tag = req_index | SRP_TAG_TSK_MGMT; + tsk_mgmt->tsk_mgmt_func = func; + tsk_mgmt->task_tag = req_index; + + if (__srp_post_send(target, iu, sizeof *tsk_mgmt)) + goto out; + + req->tsk_mgmt = iu; + + spin_unlock_irq(target->scsi_host->host_lock); + if (!wait_for_completion_timeout(&req->done, + msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS))) + return FAILED; + spin_lock_irq(target->scsi_host->host_lock); + + if (req->cmd_done) { + list_del(&req->list); + req->next = target->req_head; + target->req_head = req_index; + + scmnd->scsi_done(scmnd); + } else if (!req->tsk_status) { + scmnd->result = DID_ABORT << 16; + ret = SUCCESS; + } + +out: + spin_unlock_irq(target->scsi_host->host_lock); + return ret; +} + +static int srp_abort(struct scsi_cmnd *scmnd) +{ + printk(KERN_ERR "SRP abort called\n"); + + return srp_send_tsk_mgmt(scmnd, SRP_TSK_ABORT_TASK); +} + +static int srp_reset_device(struct scsi_cmnd *scmnd) +{ + printk(KERN_ERR "SRP reset_device called\n"); + + return srp_send_tsk_mgmt(scmnd, SRP_TSK_LUN_RESET); +} + +static int srp_reset_host(struct scsi_cmnd *scmnd) +{ + struct srp_target_port *target = host_to_target(scmnd->device->host); + int ret = FAILED; + + printk(KERN_ERR PFX "SRP reset_host called\n"); + + if (!srp_reconnect_target(target)) + ret = SUCCESS; + + return ret; +} + +static struct scsi_host_template srp_template = { + .module = THIS_MODULE, + .name = DRV_NAME, + .info = srp_target_info, + .queuecommand = srp_queuecommand, + .eh_abort_handler = srp_abort, + .eh_device_reset_handler = srp_reset_device, + .eh_host_reset_handler = srp_reset_host, + .can_queue = SRP_SQ_SIZE, + .this_id = -1, + .sg_tablesize = SRP_MAX_INDIRECT, + .cmd_per_lun = SRP_SQ_SIZE, + .use_clustering = ENABLE_CLUSTERING +}; + +static int srp_add_target(struct srp_host *host, struct srp_target_port *target) +{ + sprintf(target->target_name, "SRP.T10:%016llX", + (unsigned long long) be64_to_cpu(target->id_ext)); + + if (scsi_add_host(target->scsi_host, host->dev->dma_device)) + return -ENODEV; + + down(&host->target_mutex); + list_add_tail(&target->list, &host->target_list); + up(&host->target_mutex); + + target->state = SRP_TARGET_LIVE; + + /* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */ + scsi_scan_target(&target->scsi_host->shost_gendev, + 0, target->scsi_id, ~0, 0); + + return 0; +} + +static void srp_release_class_dev(struct class_device *class_dev) +{ + struct srp_host *host = + container_of(class_dev, struct srp_host, class_dev); + + complete(&host->released); +} + +static struct class srp_class = { + .name = "infiniband_srp", + .release = srp_release_class_dev +}; + +/* + * Target ports are added by writing + * + * id_ext=,ioc_guid=,dgid=, + * pkey=,service_id= + * + * to the add_target sysfs attribute. + */ +enum { + SRP_OPT_ERR = 0, + SRP_OPT_ID_EXT = 1 << 0, + SRP_OPT_IOC_GUID = 1 << 1, + SRP_OPT_DGID = 1 << 2, + SRP_OPT_PKEY = 1 << 3, + SRP_OPT_SERVICE_ID = 1 << 4, + SRP_OPT_MAX_SECT = 1 << 5, + SRP_OPT_ALL = (SRP_OPT_ID_EXT | + SRP_OPT_IOC_GUID | + SRP_OPT_DGID | + SRP_OPT_PKEY | + SRP_OPT_SERVICE_ID), +}; + +static match_table_t srp_opt_tokens = { + { SRP_OPT_ID_EXT, "id_ext=%s" }, + { SRP_OPT_IOC_GUID, "ioc_guid=%s" }, + { SRP_OPT_DGID, "dgid=%s" }, + { SRP_OPT_PKEY, "pkey=%x" }, + { SRP_OPT_SERVICE_ID, "service_id=%s" }, + { SRP_OPT_MAX_SECT, "max_sect=%d" }, + { SRP_OPT_ERR, NULL } +}; + +static int srp_parse_options(const char *buf, struct srp_target_port *target) +{ + char *options, *sep_opt; + char *p; + char dgid[3]; + substring_t args[MAX_OPT_ARGS]; + int opt_mask = 0; + int token; + int ret = -EINVAL; + int i; + + options = kstrdup(buf, GFP_KERNEL); + if (!options) + return -ENOMEM; + + sep_opt = options; + while ((p = strsep(&sep_opt, ",")) != NULL) { + if (!*p) + continue; + + token = match_token(p, srp_opt_tokens, args); + opt_mask |= token; + + switch (token) { + case SRP_OPT_ID_EXT: + p = match_strdup(args); + target->id_ext = cpu_to_be64(simple_strtoull(p, NULL, 16)); + kfree(p); + break; + + case SRP_OPT_IOC_GUID: + p = match_strdup(args); + target->ioc_guid = cpu_to_be64(simple_strtoull(p, NULL, 16)); + kfree(p); + break; + + case SRP_OPT_DGID: + p = match_strdup(args); + if (strlen(p) != 32) { + printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p); + goto out; + } + + for (i = 0; i < 16; ++i) { + strlcpy(dgid, p + i * 2, 3); + target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16); + } + break; + + case SRP_OPT_PKEY: + if (match_hex(args, &token)) { + printk(KERN_WARNING PFX "bad P_Key parameter '%s'\n", p); + goto out; + } + target->path.pkey = cpu_to_be16(token); + break; + + case SRP_OPT_SERVICE_ID: + p = match_strdup(args); + target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16)); + kfree(p); + break; + + case SRP_OPT_MAX_SECT: + if (match_int(args, &token)) { + printk(KERN_WARNING PFX "bad max sect parameter '%s'\n", p); + goto out; + } + target->scsi_host->max_sectors = token; + break; + + default: + printk(KERN_WARNING PFX "unknown parameter or missing value " + "'%s' in target creation request\n", p); + goto out; + } + } + + if ((opt_mask & SRP_OPT_ALL) == SRP_OPT_ALL) + ret = 0; + else + for (i = 0; i < ARRAY_SIZE(srp_opt_tokens); ++i) + if ((srp_opt_tokens[i].token & SRP_OPT_ALL) && + !(srp_opt_tokens[i].token & opt_mask)) + printk(KERN_WARNING PFX "target creation request is " + "missing parameter '%s'\n", + srp_opt_tokens[i].pattern); + +out: + kfree(options); + return ret; +} + +static ssize_t srp_create_target(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct srp_host *host = + container_of(class_dev, struct srp_host, class_dev); + struct Scsi_Host *target_host; + struct srp_target_port *target; + int ret; + int i; + + target_host = scsi_host_alloc(&srp_template, + sizeof (struct srp_target_port)); + if (!target_host) + return -ENOMEM; + + target = host_to_target(target_host); + memset(target, 0, sizeof *target); + + target->scsi_host = target_host; + target->srp_host = host; + + INIT_WORK(&target->work, srp_reconnect_work, target); + + for (i = 0; i < SRP_SQ_SIZE - 1; ++i) + target->req_ring[i].next = i + 1; + target->req_ring[SRP_SQ_SIZE - 1].next = -1; + INIT_LIST_HEAD(&target->req_queue); + + ret = srp_parse_options(buf, target); + if (ret) + goto err; + + ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid); + + printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x " + "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + (unsigned long long) be64_to_cpu(target->id_ext), + (unsigned long long) be64_to_cpu(target->ioc_guid), + be16_to_cpu(target->path.pkey), + (unsigned long long) be64_to_cpu(target->service_id), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[0]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[2]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[4]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[6]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[8]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[10]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[12]), + (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[14])); + + ret = srp_create_target_ib(target); + if (ret) + goto err; + + target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target); + if (IS_ERR(target->cm_id)) { + ret = PTR_ERR(target->cm_id); + goto err_free; + } + + ret = srp_connect_target(target); + if (ret) { + printk(KERN_ERR PFX "Connection failed\n"); + goto err_cm_id; + } + + ret = srp_add_target(host, target); + if (ret) + goto err_disconnect; + + return count; + +err_disconnect: + srp_disconnect_target(target); + +err_cm_id: + ib_destroy_cm_id(target->cm_id); + +err_free: + srp_free_target_ib(target); + +err: + scsi_host_put(target_host); + + return ret; +} + +static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target); + +static ssize_t show_ibdev(struct class_device *class_dev, char *buf) +{ + struct srp_host *host = + container_of(class_dev, struct srp_host, class_dev); + + return sprintf(buf, "%s\n", host->dev->name); +} + +static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); + +static ssize_t show_port(struct class_device *class_dev, char *buf) +{ + struct srp_host *host = + container_of(class_dev, struct srp_host, class_dev); + + return sprintf(buf, "%d\n", host->port); +} + +static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); + +static struct srp_host *srp_add_port(struct ib_device *device, + __be64 node_guid, u8 port) +{ + struct srp_host *host; + + host = kzalloc(sizeof *host, GFP_KERNEL); + if (!host) + return NULL; + + INIT_LIST_HEAD(&host->target_list); + init_MUTEX(&host->target_mutex); + init_completion(&host->released); + host->dev = device; + host->port = port; + + host->initiator_port_id[7] = port; + memcpy(host->initiator_port_id + 8, &node_guid, 8); + + host->pd = ib_alloc_pd(device); + if (IS_ERR(host->pd)) + goto err_free; + + host->mr = ib_get_dma_mr(host->pd, + IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_READ | + IB_ACCESS_REMOTE_WRITE); + if (IS_ERR(host->mr)) + goto err_pd; + + host->class_dev.class = &srp_class; + host->class_dev.dev = device->dma_device; + snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", + device->name, port); + + if (class_device_register(&host->class_dev)) + goto err_mr; + if (class_device_create_file(&host->class_dev, &class_device_attr_add_target)) + goto err_class; + if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev)) + goto err_class; + if (class_device_create_file(&host->class_dev, &class_device_attr_port)) + goto err_class; + + return host; + +err_class: + class_device_unregister(&host->class_dev); + +err_mr: + ib_dereg_mr(host->mr); + +err_pd: + ib_dealloc_pd(host->pd); + +err_free: + kfree(host); + + return NULL; +} + +static void srp_add_one(struct ib_device *device) +{ + struct list_head *dev_list; + struct srp_host *host; + struct ib_device_attr *dev_attr; + int s, e, p; + + dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); + if (!dev_attr) + return; + + if (ib_query_device(device, dev_attr)) { + printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n", + device->name); + goto out; + } + + dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); + if (!dev_list) + goto out; + + INIT_LIST_HEAD(dev_list); + + if (device->node_type == IB_NODE_SWITCH) { + s = 0; + e = 0; + } else { + s = 1; + e = device->phys_port_cnt; + } + + for (p = s; p <= e; ++p) { + host = srp_add_port(device, dev_attr->node_guid, p); + if (host) + list_add_tail(&host->list, dev_list); + } + + ib_set_client_data(device, &srp_client, dev_list); + +out: + kfree(dev_attr); +} + +static void srp_remove_one(struct ib_device *device) +{ + struct list_head *dev_list; + struct srp_host *host, *tmp_host; + LIST_HEAD(target_list); + struct srp_target_port *target, *tmp_target; + unsigned long flags; + + dev_list = ib_get_client_data(device, &srp_client); + + list_for_each_entry_safe(host, tmp_host, dev_list, list) { + class_device_unregister(&host->class_dev); + /* + * Wait for the sysfs entry to go away, so that no new + * target ports can be created. + */ + wait_for_completion(&host->released); + + /* + * Mark all target ports as removed, so we stop queueing + * commands and don't try to reconnect. + */ + down(&host->target_mutex); + list_for_each_entry_safe(target, tmp_target, + &host->target_list, list) { + spin_lock_irqsave(target->scsi_host->host_lock, flags); + if (target->state != SRP_TARGET_REMOVED) + target->state = SRP_TARGET_REMOVED; + spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + } + up(&host->target_mutex); + + /* + * Wait for any reconnection tasks that may have + * started before we marked our target ports as + * removed, and any target port removal tasks. + */ + flush_scheduled_work(); + + list_for_each_entry_safe(target, tmp_target, + &host->target_list, list) { + scsi_remove_host(target->scsi_host); + srp_disconnect_target(target); + ib_destroy_cm_id(target->cm_id); + srp_free_target_ib(target); + scsi_host_put(target->scsi_host); + } + + ib_dereg_mr(host->mr); + ib_dealloc_pd(host->pd); + kfree(host); + } + + kfree(dev_list); +} + +static int __init srp_init_module(void) +{ + int ret; + + ret = class_register(&srp_class); + if (ret) { + printk(KERN_ERR PFX "couldn't register class infiniband_srp\n"); + return ret; + } + + ret = ib_register_client(&srp_client); + if (ret) { + printk(KERN_ERR PFX "couldn't register IB client\n"); + class_unregister(&srp_class); + return ret; + } + + return 0; +} + +static void __exit srp_cleanup_module(void) +{ + ib_unregister_client(&srp_client); + class_unregister(&srp_class); +} + +module_init(srp_init_module); +module_exit(srp_cleanup_module); diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h new file mode 100644 index 000000000000..4fec28a71367 --- /dev/null +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: ib_srp.h 3932 2005-11-01 17:19:29Z roland $ + */ + +#ifndef IB_SRP_H +#define IB_SRP_H + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +enum { + SRP_PATH_REC_TIMEOUT_MS = 1000, + SRP_ABORT_TIMEOUT_MS = 5000, + + SRP_PORT_REDIRECT = 1, + SRP_DLID_REDIRECT = 2, + + SRP_MAX_IU_LEN = 256, + + SRP_RQ_SHIFT = 6, + SRP_RQ_SIZE = 1 << SRP_RQ_SHIFT, + SRP_SQ_SIZE = SRP_RQ_SIZE - 1, + SRP_CQ_SIZE = SRP_SQ_SIZE + SRP_RQ_SIZE, + + SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1) +}; + +#define SRP_OP_RECV (1 << 31) +#define SRP_MAX_INDIRECT ((SRP_MAX_IU_LEN - \ + sizeof (struct srp_cmd) - \ + sizeof (struct srp_indirect_buf)) / 16) + +enum srp_target_state { + SRP_TARGET_LIVE, + SRP_TARGET_CONNECTING, + SRP_TARGET_DEAD, + SRP_TARGET_REMOVED +}; + +struct srp_host { + u8 initiator_port_id[16]; + struct ib_device *dev; + u8 port; + struct ib_pd *pd; + struct ib_mr *mr; + struct class_device class_dev; + struct list_head target_list; + struct semaphore target_mutex; + struct completion released; + struct list_head list; +}; + +struct srp_request { + struct list_head list; + struct scsi_cmnd *scmnd; + struct srp_iu *cmd; + struct srp_iu *tsk_mgmt; + DECLARE_PCI_UNMAP_ADDR(direct_mapping) + struct completion done; + short next; + u8 cmd_done; + u8 tsk_status; +}; + +struct srp_target_port { + __be64 id_ext; + __be64 ioc_guid; + __be64 service_id; + struct srp_host *srp_host; + struct Scsi_Host *scsi_host; + char target_name[32]; + unsigned int scsi_id; + + struct ib_sa_path_rec path; + struct ib_sa_query *path_query; + int path_query_id; + + struct ib_cm_id *cm_id; + struct ib_cq *cq; + struct ib_qp *qp; + + int max_ti_iu_len; + s32 req_lim; + + unsigned rx_head; + struct srp_iu *rx_ring[SRP_RQ_SIZE]; + + unsigned tx_head; + unsigned tx_tail; + struct srp_iu *tx_ring[SRP_SQ_SIZE + 1]; + + int req_head; + struct list_head req_queue; + struct srp_request req_ring[SRP_SQ_SIZE]; + + struct work_struct work; + + struct list_head list; + struct completion done; + int status; + enum srp_target_state state; +}; + +struct srp_iu { + dma_addr_t dma; + void *buf; + size_t size; + enum dma_data_direction direction; +}; + +#endif /* IB_SRP_H */ diff --git a/include/scsi/srp.h b/include/scsi/srp.h new file mode 100644 index 000000000000..6c2681dc5b46 --- /dev/null +++ b/include/scsi/srp.h @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef SCSI_SRP_H +#define SCSI_SRP_H + +/* + * Structures and constants for the SCSI RDMA Protocol (SRP) as + * defined by the INCITS T10 committee. This file was written using + * draft Revision 16a of the SRP standard. + */ + +#include + +enum { + SRP_LOGIN_REQ = 0x00, + SRP_TSK_MGMT = 0x01, + SRP_CMD = 0x02, + SRP_I_LOGOUT = 0x03, + SRP_LOGIN_RSP = 0xc0, + SRP_RSP = 0xc1, + SRP_LOGIN_REJ = 0xc2, + SRP_T_LOGOUT = 0x80, + SRP_CRED_REQ = 0x81, + SRP_AER_REQ = 0x82, + SRP_CRED_RSP = 0x41, + SRP_AER_RSP = 0x42 +}; + +enum { + SRP_BUF_FORMAT_DIRECT = 1 << 1, + SRP_BUF_FORMAT_INDIRECT = 1 << 2 +}; + +enum { + SRP_NO_DATA_DESC = 0, + SRP_DATA_DESC_DIRECT = 1, + SRP_DATA_DESC_INDIRECT = 2 +}; + +enum { + SRP_TSK_ABORT_TASK = 0x01, + SRP_TSK_ABORT_TASK_SET = 0x02, + SRP_TSK_CLEAR_TASK_SET = 0x04, + SRP_TSK_LUN_RESET = 0x08, + SRP_TSK_CLEAR_ACA = 0x40 +}; + +enum srp_login_rej_reason { + SRP_LOGIN_REJ_UNABLE_ESTABLISH_CHANNEL = 0x00010000, + SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES = 0x00010001, + SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE = 0x00010002, + SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL = 0x00010003, + SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT = 0x00010004, + SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED = 0x00010005, + SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED = 0x00010006 +}; + +struct srp_direct_buf { + __be64 va; + __be32 key; + __be32 len; +}; + +/* + * We need the packed attribute because the SRP spec puts the list of + * descriptors at an offset of 20, which is not aligned to the size + * of struct srp_direct_buf. + */ +struct srp_indirect_buf { + struct srp_direct_buf table_desc; + __be32 len; + struct srp_direct_buf desc_list[0] __attribute__((packed)); +}; + +enum { + SRP_MULTICHAN_SINGLE = 0, + SRP_MULTICHAN_MULTI = 1 +}; + +struct srp_login_req { + u8 opcode; + u8 reserved1[7]; + u64 tag; + __be32 req_it_iu_len; + u8 reserved2[4]; + __be16 req_buf_fmt; + u8 req_flags; + u8 reserved3[5]; + u8 initiator_port_id[16]; + u8 target_port_id[16]; +}; + +struct srp_login_rsp { + u8 opcode; + u8 reserved1[3]; + __be32 req_lim_delta; + u64 tag; + __be32 max_it_iu_len; + __be32 max_ti_iu_len; + __be16 buf_fmt; + u8 rsp_flags; + u8 reserved2[25]; +}; + +struct srp_login_rej { + u8 opcode; + u8 reserved1[3]; + __be32 reason; + u64 tag; + u8 reserved2[8]; + __be16 buf_fmt; + u8 reserved3[6]; +}; + +struct srp_i_logout { + u8 opcode; + u8 reserved[7]; + u64 tag; +}; + +struct srp_t_logout { + u8 opcode; + u8 sol_not; + u8 reserved[2]; + __be32 reason; + u64 tag; +}; + +/* + * We need the packed attribute because the SRP spec only aligns the + * 8-byte LUN field to 4 bytes. + */ +struct srp_tsk_mgmt { + u8 opcode; + u8 sol_not; + u8 reserved1[6]; + u64 tag; + u8 reserved2[4]; + __be64 lun __attribute__((packed)); + u8 reserved3[2]; + u8 tsk_mgmt_func; + u8 reserved4; + u64 task_tag; + u8 reserved5[8]; +}; + +/* + * We need the packed attribute because the SRP spec only aligns the + * 8-byte LUN field to 4 bytes. + */ +struct srp_cmd { + u8 opcode; + u8 sol_not; + u8 reserved1[3]; + u8 buf_fmt; + u8 data_out_desc_cnt; + u8 data_in_desc_cnt; + u64 tag; + u8 reserved2[4]; + __be64 lun __attribute__((packed)); + u8 reserved3; + u8 task_attr; + u8 reserved4; + u8 add_cdb_len; + u8 cdb[16]; + u8 add_data[0]; +}; + +enum { + SRP_RSP_FLAG_RSPVALID = 1 << 0, + SRP_RSP_FLAG_SNSVALID = 1 << 1, + SRP_RSP_FLAG_DOOVER = 1 << 2, + SRP_RSP_FLAG_DOUNDER = 1 << 3, + SRP_RSP_FLAG_DIOVER = 1 << 4, + SRP_RSP_FLAG_DIUNDER = 1 << 5 +}; + +struct srp_rsp { + u8 opcode; + u8 sol_not; + u8 reserved1[2]; + __be32 req_lim_delta; + u64 tag; + u8 reserved2[2]; + u8 flags; + u8 status; + __be32 data_out_res_cnt; + __be32 data_in_res_cnt; + __be32 sense_data_len; + __be32 resp_data_len; + u8 data[0]; +}; + +#endif /* SCSI_SRP_H */ -- cgit v1.2.3 From a054a811597a17ffbe92bc4db04a4dc2f1b1ea55 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 2 Nov 2005 22:24:33 +0000 Subject: [ARM SMP] Add hotplug CPU infrastructure This patch adds the infrastructure to support hotplug CPU on ARM platforms. Signed-off-by: Russell King --- arch/arm/Kconfig | 7 ++++ arch/arm/kernel/irq.c | 31 +++++++++++++++++ arch/arm/kernel/process.c | 9 +++++ arch/arm/kernel/smp.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ include/asm-arm/irq.h | 1 + include/asm-arm/smp.h | 10 ++++++ 6 files changed, 143 insertions(+) (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dc6d8342e5e6..6b12d71978de 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -349,6 +349,13 @@ config NR_CPUS depends on SMP default "4" +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL + help + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu. + config PREEMPT bool "Preemptible Kernel (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 3284118f356b..9def4404e1f2 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -1050,3 +1050,34 @@ static int __init noirqdebug_setup(char *str) } __setup("noirqdebug", noirqdebug_setup); + +#ifdef CONFIG_HOTPLUG_CPU +/* + * The CPU has been marked offline. Migrate IRQs off this CPU. If + * the affinity settings do not allow other CPUs, force them onto any + * available CPU. + */ +void migrate_irqs(void) +{ + unsigned int i, cpu = smp_processor_id(); + + for (i = 0; i < NR_IRQS; i++) { + struct irqdesc *desc = irq_desc + i; + + if (desc->cpu == cpu) { + unsigned int newcpu = any_online_cpu(desc->affinity); + + if (newcpu == NR_CPUS) { + if (printk_ratelimit()) + printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", + i, cpu); + + cpus_setall(desc->affinity); + newcpu = any_online_cpu(desc->affinity); + } + + route_irq(desc, i, newcpu); + } + } +} +#endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 409db6d5ec99..ba298277becd 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,14 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { void (*idle)(void) = pm_idle; + +#ifdef CONFIG_HOTPLUG_CPU + if (cpu_is_offline(smp_processor_id())) { + leds_event(led_idle_start); + cpu_die(); + } +#endif + if (!idle) idle = default_idle; preempt_disable(); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b40915dcd533..edb5a406922f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -159,6 +159,91 @@ int __cpuinit __cpu_up(unsigned int cpu) return ret; } +#ifdef CONFIG_HOTPLUG_CPU +/* + * __cpu_disable runs on the processor to be shutdown. + */ +int __cpuexit __cpu_disable(void) +{ + unsigned int cpu = smp_processor_id(); + struct task_struct *p; + int ret; + + ret = mach_cpu_disable(cpu); + if (ret) + return ret; + + /* + * Take this CPU offline. Once we clear this, we can't return, + * and we must not schedule until we're ready to give up the cpu. + */ + cpu_clear(cpu, cpu_online_map); + + /* + * OK - migrate IRQs away from this CPU + */ + migrate_irqs(); + + /* + * Flush user cache and TLB mappings, and then remove this CPU + * from the vm mask set of all processes. + */ + flush_cache_all(); + local_flush_tlb_all(); + + read_lock(&tasklist_lock); + for_each_process(p) { + if (p->mm) + cpu_clear(cpu, p->mm->cpu_vm_mask); + } + read_unlock(&tasklist_lock); + + return 0; +} + +/* + * called on the thread which is asking for a CPU to be shutdown - + * waits until shutdown has completed, or it is timed out. + */ +void __cpuexit __cpu_die(unsigned int cpu) +{ + if (!platform_cpu_kill(cpu)) + printk("CPU%u: unable to kill\n", cpu); +} + +/* + * Called from the idle thread for the CPU which has been shutdown. + * + * Note that we disable IRQs here, but do not re-enable them + * before returning to the caller. This is also the behaviour + * of the other hotplug-cpu capable cores, so presumably coming + * out of idle fixes this. + */ +void __cpuexit cpu_die(void) +{ + unsigned int cpu = smp_processor_id(); + + local_irq_disable(); + idle_task_exit(); + + /* + * actual CPU shutdown procedure is at least platform (if not + * CPU) specific + */ + platform_cpu_die(cpu); + + /* + * Do not return to the idle loop - jump back to the secondary + * cpu initialisation. There's some initialisation which needs + * to be repeated to undo the effects of taking the CPU offline. + */ + __asm__("mov sp, %0\n" + " b secondary_start_kernel" + : + : "r" ((void *)current->thread_info + THREAD_SIZE - 8)); +} +#endif /* CONFIG_HOTPLUG_CPU */ + /* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h index f97912fbb10f..59975ee43cf1 100644 --- a/include/asm-arm/irq.h +++ b/include/asm-arm/irq.h @@ -47,5 +47,6 @@ struct irqaction; struct pt_regs; int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); +extern void migrate_irqs(void); #endif diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index dbb4d859c586..551cd3c3093c 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -66,4 +66,14 @@ struct secondary_data { }; extern struct secondary_data secondary_data; +extern int __cpu_disable(void); +extern int mach_cpu_disable(unsigned int cpu); + +extern void __cpu_die(unsigned int cpu); +extern void cpu_die(void); + +extern void platform_cpu_die(unsigned int cpu); +extern int platform_cpu_kill(unsigned int cpu); +extern void platform_cpu_enable(unsigned int cpu); + #endif /* ifndef __ASM_ARM_SMP_H */ -- cgit v1.2.3 From 2407534f8be8015d585104bcc4374870b6b70fe7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 1 Nov 2005 16:52:11 -0800 Subject: [ETHERNET]: Optimize is_broadcast_ether_addr Optimize the match for broadcast address by using bit operations instead of comparison. This saves a number of conditional branches, and generates smaller code. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/etherdevice.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index cc84934f9059..17460c85df7b 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -71,8 +71,7 @@ static inline int is_multicast_ether_addr(const u8 *addr) static inline int is_broadcast_ether_addr(const u8 *addr) { - return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && - (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; } /** -- cgit v1.2.3 From c2da8acaf488b8651edfb04ebf3ab089f3a7830f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 1 Nov 2005 17:05:09 -0800 Subject: [ETHERNET]: Add ether stuff to docbook Fix up etherdevice docbook comments and make them (and other networking stuff) get dragged into the kernel-api. Delete the old 8390 stuff, it really isn't interesting anymore. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/DocBook/kernel-api.tmpl | 6 +++--- include/linux/etherdevice.h | 24 +++++++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 4d9b66d8b4db..ec474e5a25ed 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -239,9 +239,9 @@ X!Ilib/string.c Network device support Driver Support !Enet/core/dev.c - - 8390 Based Network Cards -!Edrivers/net/8390.c +!Enet/ethernet/eth.c +!Einclude/linux/etherdevice.h +!Enet/core/wireless.c Synchronous PPP !Edrivers/net/wan/syncppp.c diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 17460c85df7b..5f49a30eb6f2 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -48,8 +48,10 @@ static inline void eth_copy_and_sum (struct sk_buff *dest, } /** - * is_zero_ether_addr - Determine if give Ethernet address is all - * zeros. + * is_zero_ether_addr - Determine if give Ethernet address is all zeros. + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is all zeroes. */ static inline int is_zero_ether_addr(const u8 *addr) { @@ -57,9 +59,7 @@ static inline int is_zero_ether_addr(const u8 *addr) } /** - * is_multicast_ether_addr - Determine if the given Ethernet address is a - * multicast address. - * + * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. * @addr: Pointer to a six-byte array containing the Ethernet address * * Return true if the address is a multicast address. @@ -69,6 +69,12 @@ static inline int is_multicast_ether_addr(const u8 *addr) return ((addr[0] != 0xff) && (0x01 & addr[0])); } +/** + * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is the broadcast address. + */ static inline int is_broadcast_ether_addr(const u8 *addr) { return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; @@ -107,14 +113,14 @@ static inline void random_ether_addr(u8 *addr) /** * compare_ether_addr - Compare two Ethernet addresses * @addr1: Pointer to a six-byte array containing the Ethernet address - * @addr2 Pointer other six-byte array containing the Ethernet address + * @addr2: Pointer other six-byte array containing the Ethernet address * * Compare two ethernet addresses, returns 0 if equal */ -static inline unsigned compare_ether_addr(const u8 *_a, const u8 *_b) +static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2) { - const u16 *a = (const u16 *) _a; - const u16 *b = (const u16 *) _b; + const u16 *a = (const u16 *) addr1; + const u16 *b = (const u16 *) addr2; BUILD_BUG_ON(ETH_ALEN != 6); return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0; -- cgit v1.2.3 From 436d7d3060fdeca91d0dd67a9ae21d4915f1410f Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 3 Nov 2005 13:50:05 +1100 Subject: [XFS] Update XFS quota header license to match the SGI boilerplate. Signed-off-by: Nathan Scott --- include/linux/dqblk_xfs.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h index cb31719ee192..c90997d9cc1e 100644 --- a/include/linux/dqblk_xfs.h +++ b/include/linux/dqblk_xfs.h @@ -1,22 +1,18 @@ /* * Copyright (c) 1995-2001,2004 Silicon Graphics, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - * Mountain View, CA 94043, USA, or: http://www.sgi.com + * You should have received a copy of the GNU Lesset General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LINUX_DQBLK_XFS_H #define _LINUX_DQBLK_XFS_H -- cgit v1.2.3 From a2f8e178ad3e576d107f5d9d47c056dd57221857 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 3 Nov 2005 13:51:23 +1100 Subject: [XFS] Add the project quota type into the XFS quota header. Signed-off-by: Nathan Scott --- include/linux/dqblk_xfs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h index c90997d9cc1e..6ad85bbd0d17 100644 --- a/include/linux/dqblk_xfs.h +++ b/include/linux/dqblk_xfs.h @@ -28,7 +28,8 @@ #define XQM_USRQUOTA 0 /* system call user quota type */ #define XQM_GRPQUOTA 1 /* system call group quota type */ -#define XQM_MAXQUOTAS 2 +#define XQM_PRJQUOTA 2 /* system call project quota type */ +#define XQM_MAXQUOTAS 3 #define Q_XQUOTAON XQM_CMD(1) /* enable accounting/enforcement */ #define Q_XQUOTAOFF XQM_CMD(2) /* disable accounting/enforcement */ -- cgit v1.2.3 From de69e5f44ecbf1d9faca4f473f4210473d26cd41 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 3 Nov 2005 13:53:34 +1100 Subject: [XFS] Add a mechanism for XFS to use the generic quota sync method. This is now used to issue a delayed allocation flush before reporting quota, which allows the used space quota report to match reality. Signed-off-by: Nathan Scott --- fs/quota.c | 8 +++++++- include/linux/dqblk_xfs.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/fs/quota.c b/fs/quota.c index f5d1cff55196..1df7832b4e08 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -118,6 +118,10 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i if (!sb->s_qcop->get_xquota) return -ENOSYS; break; + case Q_XQUOTASYNC: + if (!sb->s_qcop->quota_sync) + return -ENOSYS; + break; default: return -EINVAL; } @@ -128,7 +132,7 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i (type == XQM_GRPQUOTA && !in_egroup_p(id))) && !capable(CAP_SYS_ADMIN)) return -EPERM; - } else if (cmd != Q_XGETQSTAT) { + } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; } @@ -322,6 +326,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void return -EFAULT; return 0; } + case Q_XQUOTASYNC: + return sb->s_qcop->quota_sync(sb, type); /* We never reach here unless validity check is broken */ default: BUG(); diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h index 6ad85bbd0d17..2fda1b2aabd9 100644 --- a/include/linux/dqblk_xfs.h +++ b/include/linux/dqblk_xfs.h @@ -37,6 +37,7 @@ #define Q_XSETQLIM XQM_CMD(4) /* set disk limits */ #define Q_XGETQSTAT XQM_CMD(5) /* get quota subsystem status */ #define Q_XQUOTARM XQM_CMD(6) /* free disk space used by dquots */ +#define Q_XQUOTASYNC XQM_CMD(7) /* delalloc flush, updates dquots */ /* * fs_disk_quota structure: -- cgit v1.2.3 From f4fcbbe9a7fdf11305fea657202b954bdc2228ec Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 3 Nov 2005 14:41:19 +1100 Subject: powerpc: Merge remaining RTAS code This moves rtas-proc.c and rtas_flash.c into arch/powerpc/kernel, since cell wants them as well as pseries (and chrp can use rtas-proc.c too, at least in principle). rtas_fw.c is gone, with its bits moved into rtas_flash.c and rtas.c. Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 12 +- arch/powerpc/kernel/Makefile | 3 +- arch/powerpc/kernel/rtas-proc.c | 808 +++++++++++++++++++++++++++++++ arch/powerpc/kernel/rtas.c | 19 +- arch/powerpc/kernel/rtas_flash.c | 834 ++++++++++++++++++++++++++++++++ arch/powerpc/kernel/rtas_fw.c | 136 ------ arch/powerpc/platforms/pseries/Kconfig | 9 - arch/powerpc/platforms/pseries/Makefile | 2 +- arch/powerpc/platforms/pseries/rtasd.c | 527 ++++++++++++++++++++ arch/powerpc/platforms/pseries/setup.c | 6 +- arch/ppc64/kernel/Makefile | 4 +- arch/ppc64/kernel/rtas-proc.c | 808 ------------------------------- arch/ppc64/kernel/rtas_flash.c | 725 --------------------------- arch/ppc64/kernel/rtasd.c | 527 -------------------- include/asm-powerpc/rtas.h | 28 +- 15 files changed, 2205 insertions(+), 2243 deletions(-) create mode 100644 arch/powerpc/kernel/rtas-proc.c create mode 100644 arch/powerpc/kernel/rtas_flash.c delete mode 100644 arch/powerpc/kernel/rtas_fw.c create mode 100644 arch/powerpc/platforms/pseries/rtasd.c delete mode 100644 arch/ppc64/kernel/rtas-proc.c delete mode 100644 arch/ppc64/kernel/rtas_flash.c delete mode 100644 arch/ppc64/kernel/rtasd.c (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1c44a1dac421..3cf03ab46113 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -278,7 +278,6 @@ config PPC_PSERIES select PPC_I8259 select PPC_RTAS select RTAS_ERROR_LOGGING - select RTAS_FW default y config PPC_CHRP @@ -324,7 +323,6 @@ config PPC_CELL bool " Cell Broadband Processor Architecture" depends on PPC_MULTIPLATFORM && PPC64 select PPC_RTAS - select RTAS_FW select MMIO_NVRAM config PPC_OF @@ -356,10 +354,14 @@ config RTAS_ERROR_LOGGING depends on PPC_RTAS default n -config RTAS_FW - bool +config RTAS_PROC + bool "Proc interface to RTAS" depends on PPC_RTAS - default n + default y + +config RTAS_FLASH + tristate "Firmware flash interface" + depends on PPC64 && RTAS_PROC config MMIO_NVRAM bool diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index abad3059a21a..601ddbf1c20b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -18,7 +18,8 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_POWER4) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o obj-$(CONFIG_PPC_RTAS) += rtas.o -obj-$(CONFIG_RTAS_FW) += rtas_fw.o +obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o +obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_IBMVIO) += vio.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c new file mode 100644 index 000000000000..5bdd5b079d96 --- /dev/null +++ b/arch/powerpc/kernel/rtas-proc.c @@ -0,0 +1,808 @@ +/* + * arch/ppc64/kernel/rtas-proc.c + * Copyright (C) 2000 Tilmann Bitterberg + * (tilmann@bitterberg.de) + * + * RTAS (Runtime Abstraction Services) stuff + * Intention is to provide a clean user interface + * to use the RTAS. + * + * TODO: + * Split off a header file and maybe move it to a different + * location. Write Documentation on what the /proc/rtas/ entries + * actually do. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* for ppc_md */ +#include +#include + +/* Token for Sensors */ +#define KEY_SWITCH 0x0001 +#define ENCLOSURE_SWITCH 0x0002 +#define THERMAL_SENSOR 0x0003 +#define LID_STATUS 0x0004 +#define POWER_SOURCE 0x0005 +#define BATTERY_VOLTAGE 0x0006 +#define BATTERY_REMAINING 0x0007 +#define BATTERY_PERCENTAGE 0x0008 +#define EPOW_SENSOR 0x0009 +#define BATTERY_CYCLESTATE 0x000a +#define BATTERY_CHARGING 0x000b + +/* IBM specific sensors */ +#define IBM_SURVEILLANCE 0x2328 /* 9000 */ +#define IBM_FANRPM 0x2329 /* 9001 */ +#define IBM_VOLTAGE 0x232a /* 9002 */ +#define IBM_DRCONNECTOR 0x232b /* 9003 */ +#define IBM_POWERSUPPLY 0x232c /* 9004 */ + +/* Status return values */ +#define SENSOR_CRITICAL_HIGH 13 +#define SENSOR_WARNING_HIGH 12 +#define SENSOR_NORMAL 11 +#define SENSOR_WARNING_LOW 10 +#define SENSOR_CRITICAL_LOW 9 +#define SENSOR_SUCCESS 0 +#define SENSOR_HW_ERROR -1 +#define SENSOR_BUSY -2 +#define SENSOR_NOT_EXIST -3 +#define SENSOR_DR_ENTITY -9000 + +/* Location Codes */ +#define LOC_SCSI_DEV_ADDR 'A' +#define LOC_SCSI_DEV_LOC 'B' +#define LOC_CPU 'C' +#define LOC_DISKETTE 'D' +#define LOC_ETHERNET 'E' +#define LOC_FAN 'F' +#define LOC_GRAPHICS 'G' +/* reserved / not used 'H' */ +#define LOC_IO_ADAPTER 'I' +/* reserved / not used 'J' */ +#define LOC_KEYBOARD 'K' +#define LOC_LCD 'L' +#define LOC_MEMORY 'M' +#define LOC_NV_MEMORY 'N' +#define LOC_MOUSE 'O' +#define LOC_PLANAR 'P' +#define LOC_OTHER_IO 'Q' +#define LOC_PARALLEL 'R' +#define LOC_SERIAL 'S' +#define LOC_DEAD_RING 'T' +#define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */ +#define LOC_VOLTAGE 'V' +#define LOC_SWITCH_ADAPTER 'W' +#define LOC_OTHER 'X' +#define LOC_FIRMWARE 'Y' +#define LOC_SCSI 'Z' + +/* Tokens for indicators */ +#define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/ +#define TONE_VOLUME 0x0002 /* 0 - 100 (%) */ +#define SYSTEM_POWER_STATE 0x0003 +#define WARNING_LIGHT 0x0004 +#define DISK_ACTIVITY_LIGHT 0x0005 +#define HEX_DISPLAY_UNIT 0x0006 +#define BATTERY_WARNING_TIME 0x0007 +#define CONDITION_CYCLE_REQUEST 0x0008 +#define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */ +#define DR_ACTION 0x2329 /* 9001 */ +#define DR_INDICATOR 0x232a /* 9002 */ +/* 9003 - 9004: Vendor specific */ +/* 9006 - 9999: Vendor specific */ + +/* other */ +#define MAX_SENSORS 17 /* I only know of 17 sensors */ +#define MAX_LINELENGTH 256 +#define SENSOR_PREFIX "ibm,sensor-" +#define cel_to_fahr(x) ((x*9/5)+32) + + +/* Globals */ +static struct rtas_sensors sensors; +static struct device_node *rtas_node = NULL; +static unsigned long power_on_time = 0; /* Save the time the user set */ +static char progress_led[MAX_LINELENGTH]; + +static unsigned long rtas_tone_frequency = 1000; +static unsigned long rtas_tone_volume = 0; + +/* ****************STRUCTS******************************************* */ +struct individual_sensor { + unsigned int token; + unsigned int quant; +}; + +struct rtas_sensors { + struct individual_sensor sensor[MAX_SENSORS]; + unsigned int quant; +}; + +/* ****************************************************************** */ +/* Declarations */ +static int ppc_rtas_sensors_show(struct seq_file *m, void *v); +static int ppc_rtas_clock_show(struct seq_file *m, void *v); +static ssize_t ppc_rtas_clock_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); +static int ppc_rtas_progress_show(struct seq_file *m, void *v); +static ssize_t ppc_rtas_progress_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); +static int ppc_rtas_poweron_show(struct seq_file *m, void *v); +static ssize_t ppc_rtas_poweron_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); + +static ssize_t ppc_rtas_tone_freq_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); +static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v); +static ssize_t ppc_rtas_tone_volume_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); +static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v); +static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v); + +static int sensors_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_sensors_show, NULL); +} + +struct file_operations ppc_rtas_sensors_operations = { + .open = sensors_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int poweron_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_poweron_show, NULL); +} + +struct file_operations ppc_rtas_poweron_operations = { + .open = poweron_open, + .read = seq_read, + .llseek = seq_lseek, + .write = ppc_rtas_poweron_write, + .release = single_release, +}; + +static int progress_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_progress_show, NULL); +} + +struct file_operations ppc_rtas_progress_operations = { + .open = progress_open, + .read = seq_read, + .llseek = seq_lseek, + .write = ppc_rtas_progress_write, + .release = single_release, +}; + +static int clock_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_clock_show, NULL); +} + +struct file_operations ppc_rtas_clock_operations = { + .open = clock_open, + .read = seq_read, + .llseek = seq_lseek, + .write = ppc_rtas_clock_write, + .release = single_release, +}; + +static int tone_freq_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_tone_freq_show, NULL); +} + +struct file_operations ppc_rtas_tone_freq_operations = { + .open = tone_freq_open, + .read = seq_read, + .llseek = seq_lseek, + .write = ppc_rtas_tone_freq_write, + .release = single_release, +}; + +static int tone_volume_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_tone_volume_show, NULL); +} + +struct file_operations ppc_rtas_tone_volume_operations = { + .open = tone_volume_open, + .read = seq_read, + .llseek = seq_lseek, + .write = ppc_rtas_tone_volume_write, + .release = single_release, +}; + +static int rmo_buf_open(struct inode *inode, struct file *file) +{ + return single_open(file, ppc_rtas_rmo_buf_show, NULL); +} + +struct file_operations ppc_rtas_rmo_buf_ops = { + .open = rmo_buf_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int ppc_rtas_find_all_sensors(void); +static void ppc_rtas_process_sensor(struct seq_file *m, + struct individual_sensor *s, int state, int error, char *loc); +static char *ppc_rtas_process_error(int error); +static void get_location_code(struct seq_file *m, + struct individual_sensor *s, char *loc); +static void check_location_string(struct seq_file *m, char *c); +static void check_location(struct seq_file *m, char *c); + +static int __init proc_rtas_init(void) +{ + struct proc_dir_entry *entry; + + if (!(systemcfg->platform & PLATFORM_PSERIES)) + return 1; + + rtas_node = of_find_node_by_name(NULL, "rtas"); + if (rtas_node == NULL) + return 1; + + entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_progress_operations; + + entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_clock_operations; + + entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_poweron_operations; + + entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_sensors_operations; + + entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, + NULL); + if (entry) + entry->proc_fops = &ppc_rtas_tone_freq_operations; + + entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_tone_volume_operations; + + entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL); + if (entry) + entry->proc_fops = &ppc_rtas_rmo_buf_ops; + + return 0; +} + +__initcall(proc_rtas_init); + +static int parse_number(const char __user *p, size_t count, unsigned long *val) +{ + char buf[40]; + char *end; + + if (count > 39) + return -EINVAL; + + if (copy_from_user(buf, p, count)) + return -EFAULT; + + buf[count] = 0; + + *val = simple_strtoul(buf, &end, 10); + if (*end && *end != '\n') + return -EINVAL; + + return 0; +} + +/* ****************************************************************** */ +/* POWER-ON-TIME */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_poweron_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + struct rtc_time tm; + unsigned long nowtime; + int error = parse_number(buf, count, &nowtime); + if (error) + return error; + + power_on_time = nowtime; /* save the time */ + + to_tm(nowtime, &tm); + + error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); + if (error) + printk(KERN_WARNING "error: setting poweron time returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static int ppc_rtas_poweron_show(struct seq_file *m, void *v) +{ + if (power_on_time == 0) + seq_printf(m, "Power on time not set\n"); + else + seq_printf(m, "%lu\n",power_on_time); + return 0; +} + +/* ****************************************************************** */ +/* PROGRESS */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_progress_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long hex; + + if (count >= MAX_LINELENGTH) + count = MAX_LINELENGTH -1; + if (copy_from_user(progress_led, buf, count)) { /* save the string */ + return -EFAULT; + } + progress_led[count] = 0; + + /* Lets see if the user passed hexdigits */ + hex = simple_strtoul(progress_led, NULL, 10); + + rtas_progress ((char *)progress_led, hex); + return count; + + /* clear the line */ + /* rtas_progress(" ", 0xffff);*/ +} +/* ****************************************************************** */ +static int ppc_rtas_progress_show(struct seq_file *m, void *v) +{ + if (progress_led) + seq_printf(m, "%s\n", progress_led); + return 0; +} + +/* ****************************************************************** */ +/* CLOCK */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_clock_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + struct rtc_time tm; + unsigned long nowtime; + int error = parse_number(buf, count, &nowtime); + if (error) + return error; + + to_tm(nowtime, &tm); + error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, 0); + if (error) + printk(KERN_WARNING "error: setting the clock returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static int ppc_rtas_clock_show(struct seq_file *m, void *v) +{ + int ret[8]; + int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); + + if (error) { + printk(KERN_WARNING "error: reading the clock returned: %s\n", + ppc_rtas_process_error(error)); + seq_printf(m, "0"); + } else { + unsigned int year, mon, day, hour, min, sec; + year = ret[0]; mon = ret[1]; day = ret[2]; + hour = ret[3]; min = ret[4]; sec = ret[5]; + seq_printf(m, "%lu\n", + mktime(year, mon, day, hour, min, sec)); + } + return 0; +} + +/* ****************************************************************** */ +/* SENSOR STUFF */ +/* ****************************************************************** */ +static int ppc_rtas_sensors_show(struct seq_file *m, void *v) +{ + int i,j; + int state, error; + int get_sensor_state = rtas_token("get-sensor-state"); + + seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n"); + seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n"); + seq_printf(m, "********************************************************\n"); + + if (ppc_rtas_find_all_sensors() != 0) { + seq_printf(m, "\nNo sensors are available\n"); + return 0; + } + + for (i=0; itoken); + loc = (char *) get_property(rtas_node, rstr, &llen); + + /* A sensor may have multiple instances */ + for (j = 0, offs = 0; j <= p->quant; j++) { + error = rtas_call(get_sensor_state, 2, 2, &state, + p->token, j); + + ppc_rtas_process_sensor(m, p, state, error, loc); + seq_putc(m, '\n'); + if (loc) { + offs += strlen(loc) + 1; + loc += strlen(loc) + 1; + if (offs >= llen) + loc = NULL; + } + } + } + return 0; +} + +/* ****************************************************************** */ + +static int ppc_rtas_find_all_sensors(void) +{ + unsigned int *utmp; + int len, i; + + utmp = (unsigned int *) get_property(rtas_node, "rtas-sensors", &len); + if (utmp == NULL) { + printk (KERN_ERR "error: could not get rtas-sensors\n"); + return 1; + } + + sensors.quant = len / 8; /* int + int */ + + for (i=0; itoken) { + case KEY_SWITCH: + seq_printf(m, "Key switch:\t"); + num_states = sizeof(key_switch) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", key_switch[state]); + have_strings = 1; + } + break; + case ENCLOSURE_SWITCH: + seq_printf(m, "Enclosure switch:\t"); + num_states = sizeof(enclosure_switch) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", + enclosure_switch[state]); + have_strings = 1; + } + break; + case THERMAL_SENSOR: + seq_printf(m, "Temp. (C/F):\t"); + temperature = 1; + break; + case LID_STATUS: + seq_printf(m, "Lid status:\t"); + num_states = sizeof(lid_status) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", lid_status[state]); + have_strings = 1; + } + break; + case POWER_SOURCE: + seq_printf(m, "Power source:\t"); + num_states = sizeof(power_source) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", + power_source[state]); + have_strings = 1; + } + break; + case BATTERY_VOLTAGE: + seq_printf(m, "Battery voltage:\t"); + break; + case BATTERY_REMAINING: + seq_printf(m, "Battery remaining:\t"); + num_states = sizeof(battery_remaining) / sizeof(char *); + if (state < num_states) + { + seq_printf(m, "%s\t", + battery_remaining[state]); + have_strings = 1; + } + break; + case BATTERY_PERCENTAGE: + seq_printf(m, "Battery percentage:\t"); + break; + case EPOW_SENSOR: + seq_printf(m, "EPOW Sensor:\t"); + num_states = sizeof(epow_sensor) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", epow_sensor[state]); + have_strings = 1; + } + break; + case BATTERY_CYCLESTATE: + seq_printf(m, "Battery cyclestate:\t"); + num_states = sizeof(battery_cyclestate) / + sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", + battery_cyclestate[state]); + have_strings = 1; + } + break; + case BATTERY_CHARGING: + seq_printf(m, "Battery Charging:\t"); + num_states = sizeof(battery_charging) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", + battery_charging[state]); + have_strings = 1; + } + break; + case IBM_SURVEILLANCE: + seq_printf(m, "Surveillance:\t"); + break; + case IBM_FANRPM: + seq_printf(m, "Fan (rpm):\t"); + break; + case IBM_VOLTAGE: + seq_printf(m, "Voltage (mv):\t"); + break; + case IBM_DRCONNECTOR: + seq_printf(m, "DR connector:\t"); + num_states = sizeof(ibm_drconnector) / sizeof(char *); + if (state < num_states) { + seq_printf(m, "%s\t", + ibm_drconnector[state]); + have_strings = 1; + } + break; + case IBM_POWERSUPPLY: + seq_printf(m, "Powersupply:\t"); + break; + default: + seq_printf(m, "Unknown sensor (type %d), ignoring it\n", + s->token); + unknown = 1; + have_strings = 1; + break; + } + if (have_strings == 0) { + if (temperature) { + seq_printf(m, "%4d /%4d\t", state, cel_to_fahr(state)); + } else + seq_printf(m, "%10d\t", state); + } + if (unknown == 0) { + seq_printf(m, "%s\t", ppc_rtas_process_error(error)); + get_location_code(m, s, loc); + } +} + +/* ****************************************************************** */ + +static void check_location(struct seq_file *m, char *c) +{ + switch (c[0]) { + case LOC_PLANAR: + seq_printf(m, "Planar #%c", c[1]); + break; + case LOC_CPU: + seq_printf(m, "CPU #%c", c[1]); + break; + case LOC_FAN: + seq_printf(m, "Fan #%c", c[1]); + break; + case LOC_RACKMOUNTED: + seq_printf(m, "Rack #%c", c[1]); + break; + case LOC_VOLTAGE: + seq_printf(m, "Voltage #%c", c[1]); + break; + case LOC_LCD: + seq_printf(m, "LCD #%c", c[1]); + break; + case '.': + seq_printf(m, "- %c", c[1]); + break; + default: + seq_printf(m, "Unknown location"); + break; + } +} + + +/* ****************************************************************** */ +/* + * Format: + * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ] + * the '.' may be an abbrevation + */ +static void check_location_string(struct seq_file *m, char *c) +{ + while (*c) { + if (isalpha(*c) || *c == '.') + check_location(m, c); + else if (*c == '/' || *c == '-') + seq_printf(m, " at "); + c++; + } +} + + +/* ****************************************************************** */ + +static void get_location_code(struct seq_file *m, struct individual_sensor *s, char *loc) +{ + if (!loc || !*loc) { + seq_printf(m, "---");/* does not have a location */ + } else { + check_location_string(m, loc); + } + seq_putc(m, ' '); +} +/* ****************************************************************** */ +/* INDICATORS - Tone Frequency */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_tone_freq_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long freq; + int error = parse_number(buf, count, &freq); + if (error) + return error; + + rtas_tone_frequency = freq; /* save it for later */ + error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, + TONE_FREQUENCY, 0, freq); + if (error) + printk(KERN_WARNING "error: setting tone frequency returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%lu\n", rtas_tone_frequency); + return 0; +} +/* ****************************************************************** */ +/* INDICATORS - Tone Volume */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_tone_volume_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long volume; + int error = parse_number(buf, count, &volume); + if (error) + return error; + + if (volume > 100) + volume = 100; + + rtas_tone_volume = volume; /* save it for later */ + error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, + TONE_VOLUME, 0, volume); + if (error) + printk(KERN_WARNING "error: setting tone volume returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%lu\n", rtas_tone_volume); + return 0; +} + +#define RMO_READ_BUF_MAX 30 + +/* RTAS Userspace access */ +static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%016lx %x\n", rtas_rmo_buf, RTAS_RMOBUF_MAX); + return 0; +} diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4d22eeeeb91d..b7fc2d884950 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -42,6 +42,13 @@ DEFINE_SPINLOCK(rtas_data_buf_lock); char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; unsigned long rtas_rmo_buf; +/* + * If non-NULL, this gets called when the kernel terminates. + * This is done like this so rtas_flash can be a module. + */ +void (*rtas_flash_term_hook)(int); +EXPORT_SYMBOL(rtas_flash_term_hook); + /* * call_rtas_display_status and call_rtas_display_status_delay * are designed only for very early low-level debugging, which @@ -206,6 +213,7 @@ void rtas_progress(char *s, unsigned short hex) spin_unlock(&progress_lock); } +EXPORT_SYMBOL(rtas_progress); /* needed by rtas_flash module */ int rtas_token(const char *service) { @@ -492,6 +500,8 @@ int rtas_set_indicator(int indicator, int index, int new_value) void rtas_restart(char *cmd) { + if (rtas_flash_term_hook) + rtas_flash_term_hook(SYS_RESTART); printk("RTAS system-reboot returned %d\n", rtas_call(rtas_token("system-reboot"), 0, 1, NULL)); for (;;); @@ -499,6 +509,8 @@ void rtas_restart(char *cmd) void rtas_power_off(void) { + if (rtas_flash_term_hook) + rtas_flash_term_hook(SYS_POWER_OFF); /* allow power on only with power button press */ printk("RTAS power-off returned %d\n", rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1)); @@ -507,7 +519,12 @@ void rtas_power_off(void) void rtas_halt(void) { - rtas_power_off(); + if (rtas_flash_term_hook) + rtas_flash_term_hook(SYS_HALT); + /* allow power on only with power button press */ + printk("RTAS power-off returned %d\n", + rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1)); + for (;;); } /* Must be in the RMO region, so we place it here */ diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c new file mode 100644 index 000000000000..50500093c97f --- /dev/null +++ b/arch/powerpc/kernel/rtas_flash.c @@ -0,0 +1,834 @@ +/* + * c 2001 PPC 64 Team, IBM Corp + * + * 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. + * + * /proc/ppc64/rtas/firmware_flash interface + * + * This file implements a firmware_flash interface to pump a firmware + * image into the kernel. At reboot time rtas_restart() will see the + * firmware image and flash it as it reboots (see rtas.c). + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_VERS "1.0" +#define MODULE_NAME "rtas_flash" + +#define FIRMWARE_FLASH_NAME "firmware_flash" +#define FIRMWARE_UPDATE_NAME "firmware_update" +#define MANAGE_FLASH_NAME "manage_flash" +#define VALIDATE_FLASH_NAME "validate_flash" + +/* General RTAS Status Codes */ +#define RTAS_RC_SUCCESS 0 +#define RTAS_RC_HW_ERR -1 +#define RTAS_RC_BUSY -2 + +/* Flash image status values */ +#define FLASH_AUTH -9002 /* RTAS Not Service Authority Partition */ +#define FLASH_NO_OP -1099 /* No operation initiated by user */ +#define FLASH_IMG_SHORT -1005 /* Flash image shorter than expected */ +#define FLASH_IMG_BAD_LEN -1004 /* Bad length value in flash list block */ +#define FLASH_IMG_NULL_DATA -1003 /* Bad data value in flash list block */ +#define FLASH_IMG_READY 0 /* Firmware img ready for flash on reboot */ + +/* Manage image status values */ +#define MANAGE_AUTH -9002 /* RTAS Not Service Authority Partition */ +#define MANAGE_ACTIVE_ERR -9001 /* RTAS Cannot Overwrite Active Img */ +#define MANAGE_NO_OP -1099 /* No operation initiated by user */ +#define MANAGE_PARAM_ERR -3 /* RTAS Parameter Error */ +#define MANAGE_HW_ERR -1 /* RTAS Hardware Error */ + +/* Validate image status values */ +#define VALIDATE_AUTH -9002 /* RTAS Not Service Authority Partition */ +#define VALIDATE_NO_OP -1099 /* No operation initiated by the user */ +#define VALIDATE_INCOMPLETE -1002 /* User copied < VALIDATE_BUF_SIZE */ +#define VALIDATE_READY -1001 /* Firmware image ready for validation */ +#define VALIDATE_PARAM_ERR -3 /* RTAS Parameter Error */ +#define VALIDATE_HW_ERR -1 /* RTAS Hardware Error */ +#define VALIDATE_TMP_UPDATE 0 /* Validate Return Status */ +#define VALIDATE_FLASH_AUTH 1 /* Validate Return Status */ +#define VALIDATE_INVALID_IMG 2 /* Validate Return Status */ +#define VALIDATE_CUR_UNKNOWN 3 /* Validate Return Status */ +#define VALIDATE_TMP_COMMIT_DL 4 /* Validate Return Status */ +#define VALIDATE_TMP_COMMIT 5 /* Validate Return Status */ +#define VALIDATE_TMP_UPDATE_DL 6 /* Validate Return Status */ + +/* ibm,manage-flash-image operation tokens */ +#define RTAS_REJECT_TMP_IMG 0 +#define RTAS_COMMIT_TMP_IMG 1 + +/* Array sizes */ +#define VALIDATE_BUF_SIZE 4096 +#define RTAS_MSG_MAXLEN 64 + +struct flash_block { + char *data; + unsigned long length; +}; + +/* This struct is very similar but not identical to + * that needed by the rtas flash update. + * All we need to do for rtas is rewrite num_blocks + * into a version/length and translate the pointers + * to absolute. + */ +#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) +struct flash_block_list { + unsigned long num_blocks; + struct flash_block_list *next; + struct flash_block blocks[FLASH_BLOCKS_PER_NODE]; +}; +struct flash_block_list_header { /* just the header of flash_block_list */ + unsigned long num_blocks; + struct flash_block_list *next; +}; + +static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; + +#define FLASH_BLOCK_LIST_VERSION (1UL) + +/* Local copy of the flash block list. + * We only allow one open of the flash proc file and create this + * list as we go. This list will be put in the + * rtas_firmware_flash_list var once it is fully read. + * + * For convenience as we build the list we use virtual addrs, + * we do not fill in the version number, and the length field + * is treated as the number of entries currently in the block + * (i.e. not a byte count). This is all fixed on release. + */ + +/* Status int must be first member of struct */ +struct rtas_update_flash_t +{ + int status; /* Flash update status */ + struct flash_block_list *flist; /* Local copy of flash block list */ +}; + +/* Status int must be first member of struct */ +struct rtas_manage_flash_t +{ + int status; /* Returned status */ + unsigned int op; /* Reject or commit image */ +}; + +/* Status int must be first member of struct */ +struct rtas_validate_flash_t +{ + int status; /* Returned status */ + char buf[VALIDATE_BUF_SIZE]; /* Candidate image buffer */ + unsigned int buf_size; /* Size of image buf */ + unsigned int update_results; /* Update results token */ +}; + +static DEFINE_SPINLOCK(flash_file_open_lock); +static struct proc_dir_entry *firmware_flash_pde; +static struct proc_dir_entry *firmware_update_pde; +static struct proc_dir_entry *validate_pde; +static struct proc_dir_entry *manage_pde; + +/* Do simple sanity checks on the flash image. */ +static int flash_list_valid(struct flash_block_list *flist) +{ + struct flash_block_list *f; + int i; + unsigned long block_size, image_size; + + /* Paranoid self test here. We also collect the image size. */ + image_size = 0; + for (f = flist; f; f = f->next) { + for (i = 0; i < f->num_blocks; i++) { + if (f->blocks[i].data == NULL) { + return FLASH_IMG_NULL_DATA; + } + block_size = f->blocks[i].length; + if (block_size <= 0 || block_size > PAGE_SIZE) { + return FLASH_IMG_BAD_LEN; + } + image_size += block_size; + } + } + + if (image_size < (256 << 10)) { + if (image_size < 2) + return FLASH_NO_OP; + } + + printk(KERN_INFO "FLASH: flash image with %ld bytes stored for hardware flash on reboot\n", image_size); + + return FLASH_IMG_READY; +} + +static void free_flash_list(struct flash_block_list *f) +{ + struct flash_block_list *next; + int i; + + while (f) { + for (i = 0; i < f->num_blocks; i++) + free_page((unsigned long)(f->blocks[i].data)); + next = f->next; + free_page((unsigned long)f); + f = next; + } +} + +static int rtas_flash_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_update_flash_t *uf; + + uf = (struct rtas_update_flash_t *) dp->data; + if (uf->flist) { + /* File was opened in write mode for a new flash attempt */ + /* Clear saved list */ + if (rtas_firmware_flash_list.next) { + free_flash_list(rtas_firmware_flash_list.next); + rtas_firmware_flash_list.next = NULL; + } + + if (uf->status != FLASH_AUTH) + uf->status = flash_list_valid(uf->flist); + + if (uf->status == FLASH_IMG_READY) + rtas_firmware_flash_list.next = uf->flist; + else + free_flash_list(uf->flist); + + uf->flist = NULL; + } + + atomic_dec(&dp->count); + return 0; +} + +static void get_flash_status_msg(int status, char *buf) +{ + char *msg; + + switch (status) { + case FLASH_AUTH: + msg = "error: this partition does not have service authority\n"; + break; + case FLASH_NO_OP: + msg = "info: no firmware image for flash\n"; + break; + case FLASH_IMG_SHORT: + msg = "error: flash image short\n"; + break; + case FLASH_IMG_BAD_LEN: + msg = "error: internal error bad length\n"; + break; + case FLASH_IMG_NULL_DATA: + msg = "error: internal error null data\n"; + break; + case FLASH_IMG_READY: + msg = "ready: firmware image ready for flash on reboot\n"; + break; + default: + sprintf(buf, "error: unexpected status value %d\n", status); + return; + } + + strcpy(buf, msg); +} + +/* Reading the proc file will show status (not the firmware contents) */ +static ssize_t rtas_flash_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_update_flash_t *uf; + char msg[RTAS_MSG_MAXLEN]; + int msglen; + + uf = (struct rtas_update_flash_t *) dp->data; + + if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) { + get_flash_status_msg(uf->status, msg); + } else { /* FIRMWARE_UPDATE_NAME */ + sprintf(msg, "%d\n", uf->status); + } + msglen = strlen(msg); + if (msglen > count) + msglen = count; + + if (ppos && *ppos != 0) + return 0; /* be cheap */ + + if (!access_ok(VERIFY_WRITE, buf, msglen)) + return -EINVAL; + + if (copy_to_user(buf, msg, msglen)) + return -EFAULT; + + if (ppos) + *ppos = msglen; + return msglen; +} + +/* We could be much more efficient here. But to keep this function + * simple we allocate a page to the block list no matter how small the + * count is. If the system is low on memory it will be just as well + * that we fail.... + */ +static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, + size_t count, loff_t *off) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_update_flash_t *uf; + char *p; + int next_free; + struct flash_block_list *fl; + + uf = (struct rtas_update_flash_t *) dp->data; + + if (uf->status == FLASH_AUTH || count == 0) + return count; /* discard data */ + + /* In the case that the image is not ready for flashing, the memory + * allocated for the block list will be freed upon the release of the + * proc file + */ + if (uf->flist == NULL) { + uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); + if (!uf->flist) + return -ENOMEM; + } + + fl = uf->flist; + while (fl->next) + fl = fl->next; /* seek to last block_list for append */ + next_free = fl->num_blocks; + if (next_free == FLASH_BLOCKS_PER_NODE) { + /* Need to allocate another block_list */ + fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); + if (!fl->next) + return -ENOMEM; + fl = fl->next; + next_free = 0; + } + + if (count > PAGE_SIZE) + count = PAGE_SIZE; + p = (char *)get_zeroed_page(GFP_KERNEL); + if (!p) + return -ENOMEM; + + if(copy_from_user(p, buffer, count)) { + free_page((unsigned long)p); + return -EFAULT; + } + fl->blocks[next_free].data = p; + fl->blocks[next_free].length = count; + fl->num_blocks++; + + return count; +} + +static int rtas_excl_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(inode); + + /* Enforce exclusive open with use count of PDE */ + spin_lock(&flash_file_open_lock); + if (atomic_read(&dp->count) > 1) { + spin_unlock(&flash_file_open_lock); + return -EBUSY; + } + + atomic_inc(&dp->count); + spin_unlock(&flash_file_open_lock); + + return 0; +} + +static int rtas_excl_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(inode); + + atomic_dec(&dp->count); + + return 0; +} + +static void manage_flash(struct rtas_manage_flash_t *args_buf) +{ + unsigned int wait_time; + s32 rc; + + while (1) { + rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, + 1, NULL, args_buf->op); + if (rc == RTAS_RC_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } else + break; + } + + args_buf->status = rc; +} + +static ssize_t manage_flash_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_manage_flash_t *args_buf; + char msg[RTAS_MSG_MAXLEN]; + int msglen; + + args_buf = (struct rtas_manage_flash_t *) dp->data; + if (args_buf == NULL) + return 0; + + msglen = sprintf(msg, "%d\n", args_buf->status); + if (msglen > count) + msglen = count; + + if (ppos && *ppos != 0) + return 0; /* be cheap */ + + if (!access_ok(VERIFY_WRITE, buf, msglen)) + return -EINVAL; + + if (copy_to_user(buf, msg, msglen)) + return -EFAULT; + + if (ppos) + *ppos = msglen; + return msglen; +} + +static ssize_t manage_flash_write(struct file *file, const char __user *buf, + size_t count, loff_t *off) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_manage_flash_t *args_buf; + const char reject_str[] = "0"; + const char commit_str[] = "1"; + char stkbuf[10]; + int op; + + args_buf = (struct rtas_manage_flash_t *) dp->data; + if ((args_buf->status == MANAGE_AUTH) || (count == 0)) + return count; + + op = -1; + if (buf) { + if (count > 9) count = 9; + if (copy_from_user (stkbuf, buf, count)) { + return -EFAULT; + } + if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0) + op = RTAS_REJECT_TMP_IMG; + else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0) + op = RTAS_COMMIT_TMP_IMG; + } + + if (op == -1) /* buf is empty, or contains invalid string */ + return -EINVAL; + + args_buf->op = op; + manage_flash(args_buf); + + return count; +} + +static void validate_flash(struct rtas_validate_flash_t *args_buf) +{ + int token = rtas_token("ibm,validate-flash-image"); + unsigned int wait_time; + int update_results; + s32 rc; + + rc = 0; + while(1) { + spin_lock(&rtas_data_buf_lock); + memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); + rc = rtas_call(token, 2, 2, &update_results, + (u32) __pa(rtas_data_buf), args_buf->buf_size); + memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); + spin_unlock(&rtas_data_buf_lock); + + if (rc == RTAS_RC_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } else + break; + } + + args_buf->status = rc; + args_buf->update_results = update_results; +} + +static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, + char *msg) +{ + int n; + + if (args_buf->status >= VALIDATE_TMP_UPDATE) { + n = sprintf(msg, "%d\n", args_buf->update_results); + if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || + (args_buf->update_results == VALIDATE_TMP_UPDATE)) + n += sprintf(msg + n, "%s\n", args_buf->buf); + } else { + n = sprintf(msg, "%d\n", args_buf->status); + } + return n; +} + +static ssize_t validate_flash_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_validate_flash_t *args_buf; + char msg[RTAS_MSG_MAXLEN]; + int msglen; + + args_buf = (struct rtas_validate_flash_t *) dp->data; + + if (ppos && *ppos != 0) + return 0; /* be cheap */ + + msglen = get_validate_flash_msg(args_buf, msg); + if (msglen > count) + msglen = count; + + if (!access_ok(VERIFY_WRITE, buf, msglen)) + return -EINVAL; + + if (copy_to_user(buf, msg, msglen)) + return -EFAULT; + + if (ppos) + *ppos = msglen; + return msglen; +} + +static ssize_t validate_flash_write(struct file *file, const char __user *buf, + size_t count, loff_t *off) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_validate_flash_t *args_buf; + int rc; + + args_buf = (struct rtas_validate_flash_t *) dp->data; + + if (dp->data == NULL) { + dp->data = kmalloc(sizeof(struct rtas_validate_flash_t), + GFP_KERNEL); + if (dp->data == NULL) + return -ENOMEM; + } + + /* We are only interested in the first 4K of the + * candidate image */ + if ((*off >= VALIDATE_BUF_SIZE) || + (args_buf->status == VALIDATE_AUTH)) { + *off += count; + return count; + } + + if (*off + count >= VALIDATE_BUF_SIZE) { + count = VALIDATE_BUF_SIZE - *off; + args_buf->status = VALIDATE_READY; + } else { + args_buf->status = VALIDATE_INCOMPLETE; + } + + if (!access_ok(VERIFY_READ, buf, count)) { + rc = -EFAULT; + goto done; + } + if (copy_from_user(args_buf->buf + *off, buf, count)) { + rc = -EFAULT; + goto done; + } + + *off += count; + rc = count; +done: + if (rc < 0) { + kfree(dp->data); + dp->data = NULL; + } + return rc; +} + +static int validate_flash_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_validate_flash_t *args_buf; + + args_buf = (struct rtas_validate_flash_t *) dp->data; + + if (args_buf->status == VALIDATE_READY) { + args_buf->buf_size = VALIDATE_BUF_SIZE; + validate_flash(args_buf); + } + + /* The matching atomic_inc was in rtas_excl_open() */ + atomic_dec(&dp->count); + + return 0; +} + +static void rtas_flash_firmware(int reboot_type) +{ + unsigned long image_size; + struct flash_block_list *f, *next, *flist; + unsigned long rtas_block_list; + int i, status, update_token; + + if (rtas_firmware_flash_list.next == NULL) + return; /* nothing to do */ + + if (reboot_type != SYS_RESTART) { + printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); + printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); + return; + } + + update_token = rtas_token("ibm,update-flash-64-and-reboot"); + if (update_token == RTAS_UNKNOWN_SERVICE) { + printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot " + "is not available -- not a service partition?\n"); + printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); + return; + } + + /* NOTE: the "first" block list is a global var with no data + * blocks in the kernel data segment. We do this because + * we want to ensure this block_list addr is under 4GB. + */ + rtas_firmware_flash_list.num_blocks = 0; + flist = (struct flash_block_list *)&rtas_firmware_flash_list; + rtas_block_list = virt_to_abs(flist); + if (rtas_block_list >= 4UL*1024*1024*1024) { + printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); + return; + } + + printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); + /* Update the block_list in place. */ + image_size = 0; + for (f = flist; f; f = next) { + /* Translate data addrs to absolute */ + for (i = 0; i < f->num_blocks; i++) { + f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); + image_size += f->blocks[i].length; + } + next = f->next; + /* Don't translate NULL pointer for last entry */ + if (f->next) + f->next = (struct flash_block_list *)virt_to_abs(f->next); + else + f->next = NULL; + /* make num_blocks into the version/length field */ + f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); + } + + printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); + printk(KERN_ALERT "FLASH: performing flash and reboot\n"); + rtas_progress("Flashing \n", 0x0); + rtas_progress("Please Wait... ", 0x0); + printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); + status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); + switch (status) { /* should only get "bad" status */ + case 0: + printk(KERN_ALERT "FLASH: success\n"); + break; + case -1: + printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); + break; + case -3: + printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); + break; + case -4: + printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); + break; + default: + printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); + break; + } +} + +static void remove_flash_pde(struct proc_dir_entry *dp) +{ + if (dp) { + if (dp->data != NULL) + kfree(dp->data); + dp->owner = NULL; + remove_proc_entry(dp->name, dp->parent); + } +} + +static int initialize_flash_pde_data(const char *rtas_call_name, + size_t buf_size, + struct proc_dir_entry *dp) +{ + int *status; + int token; + + dp->data = kmalloc(buf_size, GFP_KERNEL); + if (dp->data == NULL) { + remove_flash_pde(dp); + return -ENOMEM; + } + + memset(dp->data, 0, buf_size); + + /* + * This code assumes that the status int is the first member of the + * struct + */ + status = (int *) dp->data; + token = rtas_token(rtas_call_name); + if (token == RTAS_UNKNOWN_SERVICE) + *status = FLASH_AUTH; + else + *status = FLASH_NO_OP; + + return 0; +} + +static struct proc_dir_entry *create_flash_pde(const char *filename, + struct file_operations *fops) +{ + struct proc_dir_entry *ent = NULL; + + ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL); + if (ent != NULL) { + ent->nlink = 1; + ent->proc_fops = fops; + ent->owner = THIS_MODULE; + } + + return ent; +} + +static struct file_operations rtas_flash_operations = { + .read = rtas_flash_read, + .write = rtas_flash_write, + .open = rtas_excl_open, + .release = rtas_flash_release, +}; + +static struct file_operations manage_flash_operations = { + .read = manage_flash_read, + .write = manage_flash_write, + .open = rtas_excl_open, + .release = rtas_excl_release, +}; + +static struct file_operations validate_flash_operations = { + .read = validate_flash_read, + .write = validate_flash_write, + .open = rtas_excl_open, + .release = validate_flash_release, +}; + +int __init rtas_flash_init(void) +{ + int rc; + + if (rtas_token("ibm,update-flash-64-and-reboot") == + RTAS_UNKNOWN_SERVICE) { + printk(KERN_ERR "rtas_flash: no firmware flash support\n"); + return 1; + } + + firmware_flash_pde = create_flash_pde("ppc64/rtas/" + FIRMWARE_FLASH_NAME, + &rtas_flash_operations); + if (firmware_flash_pde == NULL) { + rc = -ENOMEM; + goto cleanup; + } + + rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", + sizeof(struct rtas_update_flash_t), + firmware_flash_pde); + if (rc != 0) + goto cleanup; + + firmware_update_pde = create_flash_pde("ppc64/rtas/" + FIRMWARE_UPDATE_NAME, + &rtas_flash_operations); + if (firmware_update_pde == NULL) { + rc = -ENOMEM; + goto cleanup; + } + + rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", + sizeof(struct rtas_update_flash_t), + firmware_update_pde); + if (rc != 0) + goto cleanup; + + validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME, + &validate_flash_operations); + if (validate_pde == NULL) { + rc = -ENOMEM; + goto cleanup; + } + + rc = initialize_flash_pde_data("ibm,validate-flash-image", + sizeof(struct rtas_validate_flash_t), + validate_pde); + if (rc != 0) + goto cleanup; + + manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME, + &manage_flash_operations); + if (manage_pde == NULL) { + rc = -ENOMEM; + goto cleanup; + } + + rc = initialize_flash_pde_data("ibm,manage-flash-image", + sizeof(struct rtas_manage_flash_t), + manage_pde); + if (rc != 0) + goto cleanup; + + rtas_flash_term_hook = rtas_flash_firmware; + return 0; + +cleanup: + remove_flash_pde(firmware_flash_pde); + remove_flash_pde(firmware_update_pde); + remove_flash_pde(validate_pde); + remove_flash_pde(manage_pde); + + return rc; +} + +void __exit rtas_flash_cleanup(void) +{ + rtas_flash_term_hook = NULL; + remove_flash_pde(firmware_flash_pde); + remove_flash_pde(firmware_update_pde); + remove_flash_pde(validate_pde); + remove_flash_pde(manage_pde); +} + +module_init(rtas_flash_init); +module_exit(rtas_flash_cleanup); +MODULE_LICENSE("GPL"); diff --git a/arch/powerpc/kernel/rtas_fw.c b/arch/powerpc/kernel/rtas_fw.c deleted file mode 100644 index 448922e8af1b..000000000000 --- a/arch/powerpc/kernel/rtas_fw.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * Procedures for firmware flash updates. - * - * Peter Bergner, IBM March 2001. - * Copyright (C) 2001 IBM. - * - * 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; - -#define FLASH_BLOCK_LIST_VERSION (1UL) - -static void rtas_flash_firmware(void) -{ - unsigned long image_size; - struct flash_block_list *f, *next, *flist; - unsigned long rtas_block_list; - int i, status, update_token; - - update_token = rtas_token("ibm,update-flash-64-and-reboot"); - if (update_token == RTAS_UNKNOWN_SERVICE) { - printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n"); - printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); - return; - } - - /* NOTE: the "first" block list is a global var with no data - * blocks in the kernel data segment. We do this because - * we want to ensure this block_list addr is under 4GB. - */ - rtas_firmware_flash_list.num_blocks = 0; - flist = (struct flash_block_list *)&rtas_firmware_flash_list; - rtas_block_list = virt_to_abs(flist); - if (rtas_block_list >= 4UL*1024*1024*1024) { - printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); - return; - } - - printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); - /* Update the block_list in place. */ - image_size = 0; - for (f = flist; f; f = next) { - /* Translate data addrs to absolute */ - for (i = 0; i < f->num_blocks; i++) { - f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); - image_size += f->blocks[i].length; - } - next = f->next; - /* Don't translate NULL pointer for last entry */ - if (f->next) - f->next = (struct flash_block_list *)virt_to_abs(f->next); - else - f->next = NULL; - /* make num_blocks into the version/length field */ - f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); - } - - printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); - printk(KERN_ALERT "FLASH: performing flash and reboot\n"); - rtas_progress("Flashing \n", 0x0); - rtas_progress("Please Wait... ", 0x0); - printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); - status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); - switch (status) { /* should only get "bad" status */ - case 0: - printk(KERN_ALERT "FLASH: success\n"); - break; - case -1: - printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); - break; - case -3: - printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); - break; - case -4: - printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); - break; - default: - printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); - break; - } -} - -void rtas_flash_bypass_warning(void) -{ - printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); - printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); -} - - -void rtas_fw_restart(char *cmd) -{ - if (rtas_firmware_flash_list.next) - rtas_flash_firmware(); - rtas_restart(cmd); -} - -void rtas_fw_power_off(void) -{ - if (rtas_firmware_flash_list.next) - rtas_flash_bypass_warning(); - rtas_power_off(); -} - -void rtas_fw_halt(void) -{ - if (rtas_firmware_flash_list.next) - rtas_flash_bypass_warning(); - rtas_halt(); -} - -EXPORT_SYMBOL(rtas_firmware_flash_list); diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 2d57f588151d..e3fc3407bb1f 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -21,15 +21,6 @@ config EEH depends on PPC_PSERIES default y if !EMBEDDED -config RTAS_PROC - bool "Proc interface to RTAS" - depends on PPC_RTAS - default y - -config RTAS_FLASH - tristate "Firmware flash interface" - depends on PPC64 && RTAS_PROC - config SCANLOG tristate "Scanlog dump interface" depends on RTAS_PROC && PPC_PSERIES diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 91909a844736..b9938fece781 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,5 +1,5 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o + setup.o iommu.o ras.o rtasd.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c new file mode 100644 index 000000000000..e26b0420b6dd --- /dev/null +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -0,0 +1,527 @@ +/* + * Copyright (C) 2001 Anton Blanchard , IBM + * + * 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. + * + * Communication to userspace based on kernel/printk.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUG(A...) printk(KERN_ERR A) +#else +#define DEBUG(A...) +#endif + +static DEFINE_SPINLOCK(rtasd_log_lock); + +DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); + +static char *rtas_log_buf; +static unsigned long rtas_log_start; +static unsigned long rtas_log_size; + +static int surveillance_timeout = -1; +static unsigned int rtas_event_scan_rate; +static unsigned int rtas_error_log_max; +static unsigned int rtas_error_log_buffer_max; + +static int full_rtas_msgs = 0; + +extern int no_logging; + +volatile int error_log_cnt = 0; + +/* + * Since we use 32 bit RTAS, the physical address of this must be below + * 4G or else bad things happen. Allocate this in the kernel data and + * make it big enough. + */ +static unsigned char logdata[RTAS_ERROR_LOG_MAX]; + +static int get_eventscan_parms(void); + +static char *rtas_type[] = { + "Unknown", "Retry", "TCE Error", "Internal Device Failure", + "Timeout", "Data Parity", "Address Parity", "Cache Parity", + "Address Invalid", "ECC Uncorrected", "ECC Corrupted", +}; + +static char *rtas_event_type(int type) +{ + if ((type > 0) && (type < 11)) + return rtas_type[type]; + + switch (type) { + case RTAS_TYPE_EPOW: + return "EPOW"; + case RTAS_TYPE_PLATFORM: + return "Platform Error"; + case RTAS_TYPE_IO: + return "I/O Event"; + case RTAS_TYPE_INFO: + return "Platform Information Event"; + case RTAS_TYPE_DEALLOC: + return "Resource Deallocation Event"; + case RTAS_TYPE_DUMP: + return "Dump Notification Event"; + } + + return rtas_type[0]; +} + +/* To see this info, grep RTAS /var/log/messages and each entry + * will be collected together with obvious begin/end. + * There will be a unique identifier on the begin and end lines. + * This will persist across reboots. + * + * format of error logs returned from RTAS: + * bytes (size) : contents + * -------------------------------------------------------- + * 0-7 (8) : rtas_error_log + * 8-47 (40) : extended info + * 48-51 (4) : vendor id + * 52-1023 (vendor specific) : location code and debug data + */ +static void printk_log_rtas(char *buf, int len) +{ + + int i,j,n = 0; + int perline = 16; + char buffer[64]; + char * str = "RTAS event"; + + if (full_rtas_msgs) { + printk(RTAS_DEBUG "%d -------- %s begin --------\n", + error_log_cnt, str); + + /* + * Print perline bytes on each line, each line will start + * with RTAS and a changing number, so syslogd will + * print lines that are otherwise the same. Separate every + * 4 bytes with a space. + */ + for (i = 0; i < len; i++) { + j = i % perline; + if (j == 0) { + memset(buffer, 0, sizeof(buffer)); + n = sprintf(buffer, "RTAS %d:", i/perline); + } + + if ((i % 4) == 0) + n += sprintf(buffer+n, " "); + + n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]); + + if (j == (perline-1)) + printk(KERN_DEBUG "%s\n", buffer); + } + if ((i % perline) != 0) + printk(KERN_DEBUG "%s\n", buffer); + + printk(RTAS_DEBUG "%d -------- %s end ----------\n", + error_log_cnt, str); + } else { + struct rtas_error_log *errlog = (struct rtas_error_log *)buf; + + printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n", + error_log_cnt, rtas_event_type(errlog->type), + errlog->severity); + } +} + +static int log_rtas_len(char * buf) +{ + int len; + struct rtas_error_log *err; + + /* rtas fixed header */ + len = 8; + err = (struct rtas_error_log *)buf; + if (err->extended_log_length) { + + /* extended header */ + len += err->extended_log_length; + } + + if (rtas_error_log_max == 0) { + get_eventscan_parms(); + } + if (len > rtas_error_log_max) + len = rtas_error_log_max; + + return len; +} + +/* + * First write to nvram, if fatal error, that is the only + * place we log the info. The error will be picked up + * on the next reboot by rtasd. If not fatal, run the + * method for the type of error. Currently, only RTAS + * errors have methods implemented, but in the future + * there might be a need to store data in nvram before a + * call to panic(). + * + * XXX We write to nvram periodically, to indicate error has + * been written and sync'd, but there is a possibility + * that if we don't shutdown correctly, a duplicate error + * record will be created on next reboot. + */ +void pSeries_log_error(char *buf, unsigned int err_type, int fatal) +{ + unsigned long offset; + unsigned long s; + int len = 0; + + DEBUG("logging event\n"); + if (buf == NULL) + return; + + spin_lock_irqsave(&rtasd_log_lock, s); + + /* get length and increase count */ + switch (err_type & ERR_TYPE_MASK) { + case ERR_TYPE_RTAS_LOG: + len = log_rtas_len(buf); + if (!(err_type & ERR_FLAG_BOOT)) + error_log_cnt++; + break; + case ERR_TYPE_KERNEL_PANIC: + default: + spin_unlock_irqrestore(&rtasd_log_lock, s); + return; + } + + /* Write error to NVRAM */ + if (!no_logging && !(err_type & ERR_FLAG_BOOT)) + nvram_write_error_log(buf, len, err_type); + + /* + * rtas errors can occur during boot, and we do want to capture + * those somewhere, even if nvram isn't ready (why not?), and even + * if rtasd isn't ready. Put them into the boot log, at least. + */ + if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG) + printk_log_rtas(buf, len); + + /* Check to see if we need to or have stopped logging */ + if (fatal || no_logging) { + no_logging = 1; + spin_unlock_irqrestore(&rtasd_log_lock, s); + return; + } + + /* call type specific method for error */ + switch (err_type & ERR_TYPE_MASK) { + case ERR_TYPE_RTAS_LOG: + offset = rtas_error_log_buffer_max * + ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); + + /* First copy over sequence number */ + memcpy(&rtas_log_buf[offset], (void *) &error_log_cnt, sizeof(int)); + + /* Second copy over error log data */ + offset += sizeof(int); + memcpy(&rtas_log_buf[offset], buf, len); + + if (rtas_log_size < LOG_NUMBER) + rtas_log_size += 1; + else + rtas_log_start += 1; + + spin_unlock_irqrestore(&rtasd_log_lock, s); + wake_up_interruptible(&rtas_log_wait); + break; + case ERR_TYPE_KERNEL_PANIC: + default: + spin_unlock_irqrestore(&rtasd_log_lock, s); + return; + } + +} + + +static int rtas_log_open(struct inode * inode, struct file * file) +{ + return 0; +} + +static int rtas_log_release(struct inode * inode, struct file * file) +{ + return 0; +} + +/* This will check if all events are logged, if they are then, we + * know that we can safely clear the events in NVRAM. + * Next we'll sit and wait for something else to log. + */ +static ssize_t rtas_log_read(struct file * file, char __user * buf, + size_t count, loff_t *ppos) +{ + int error; + char *tmp; + unsigned long s; + unsigned long offset; + + if (!buf || count < rtas_error_log_buffer_max) + return -EINVAL; + + count = rtas_error_log_buffer_max; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + tmp = kmalloc(count, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + + spin_lock_irqsave(&rtasd_log_lock, s); + /* if it's 0, then we know we got the last one (the one in NVRAM) */ + if (rtas_log_size == 0 && !no_logging) + nvram_clear_error_log(); + spin_unlock_irqrestore(&rtasd_log_lock, s); + + + error = wait_event_interruptible(rtas_log_wait, rtas_log_size); + if (error) + goto out; + + spin_lock_irqsave(&rtasd_log_lock, s); + offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK); + memcpy(tmp, &rtas_log_buf[offset], count); + + rtas_log_start += 1; + rtas_log_size -= 1; + spin_unlock_irqrestore(&rtasd_log_lock, s); + + error = copy_to_user(buf, tmp, count) ? -EFAULT : count; +out: + kfree(tmp); + return error; +} + +static unsigned int rtas_log_poll(struct file *file, poll_table * wait) +{ + poll_wait(file, &rtas_log_wait, wait); + if (rtas_log_size) + return POLLIN | POLLRDNORM; + return 0; +} + +struct file_operations proc_rtas_log_operations = { + .read = rtas_log_read, + .poll = rtas_log_poll, + .open = rtas_log_open, + .release = rtas_log_release, +}; + +static int enable_surveillance(int timeout) +{ + int error; + + error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout); + + if (error == 0) + return 0; + + if (error == -EINVAL) { + printk(KERN_INFO "rtasd: surveillance not supported\n"); + return 0; + } + + printk(KERN_ERR "rtasd: could not update surveillance\n"); + return -1; +} + +static int get_eventscan_parms(void) +{ + struct device_node *node; + int *ip; + + node = of_find_node_by_path("/rtas"); + + ip = (int *)get_property(node, "rtas-event-scan-rate", NULL); + if (ip == NULL) { + printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); + of_node_put(node); + return -1; + } + rtas_event_scan_rate = *ip; + DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate); + + /* Make room for the sequence number */ + rtas_error_log_max = rtas_get_error_log_max(); + rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); + + of_node_put(node); + + return 0; +} + +static void do_event_scan(int event_scan) +{ + int error; + do { + memset(logdata, 0, rtas_error_log_max); + error = rtas_call(event_scan, 4, 1, NULL, + RTAS_EVENT_SCAN_ALL_EVENTS, 0, + __pa(logdata), rtas_error_log_max); + if (error == -1) { + printk(KERN_ERR "event-scan failed\n"); + break; + } + + if (error == 0) + pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); + + } while(error == 0); +} + +static void do_event_scan_all_cpus(long delay) +{ + int cpu; + + lock_cpu_hotplug(); + cpu = first_cpu(cpu_online_map); + for (;;) { + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + do_event_scan(rtas_token("event-scan")); + set_cpus_allowed(current, CPU_MASK_ALL); + + /* Drop hotplug lock, and sleep for the specified delay */ + unlock_cpu_hotplug(); + msleep_interruptible(delay); + lock_cpu_hotplug(); + + cpu = next_cpu(cpu, cpu_online_map); + if (cpu == NR_CPUS) + break; + } + unlock_cpu_hotplug(); +} + +static int rtasd(void *unused) +{ + unsigned int err_type; + int event_scan = rtas_token("event-scan"); + int rc; + + daemonize("rtasd"); + + if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1) + goto error; + + rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER); + if (!rtas_log_buf) { + printk(KERN_ERR "rtasd: no memory\n"); + goto error; + } + + printk(KERN_INFO "RTAS daemon started\n"); + + DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); + + /* See if we have any error stored in NVRAM */ + memset(logdata, 0, rtas_error_log_max); + + rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type); + + /* We can use rtas_log_buf now */ + no_logging = 0; + + if (!rc) { + if (err_type != ERR_FLAG_ALREADY_LOGGED) { + pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); + } + } + + /* First pass. */ + do_event_scan_all_cpus(1000); + + if (surveillance_timeout != -1) { + DEBUG("enabling surveillance\n"); + enable_surveillance(surveillance_timeout); + DEBUG("surveillance enabled\n"); + } + + /* Delay should be at least one second since some + * machines have problems if we call event-scan too + * quickly. */ + for (;;) + do_event_scan_all_cpus(30000/rtas_event_scan_rate); + +error: + /* Should delete proc entries */ + return -EINVAL; +} + +static int __init rtas_init(void) +{ + struct proc_dir_entry *entry; + + /* No RTAS, only warn if we are on a pSeries box */ + if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { + if (systemcfg->platform & PLATFORM_PSERIES) + printk(KERN_INFO "rtasd: no event-scan on system\n"); + return 1; + } + + entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL); + if (entry) + entry->proc_fops = &proc_rtas_log_operations; + else + printk(KERN_ERR "Failed to create error_log proc entry\n"); + + if (kernel_thread(rtasd, NULL, CLONE_FS) < 0) + printk(KERN_ERR "Failed to start RTAS daemon\n"); + + return 0; +} + +static int __init surveillance_setup(char *str) +{ + int i; + + if (get_option(&str,&i)) { + if (i >= 0 && i <= 255) + surveillance_timeout = i; + } + + return 1; +} + +static int __init rtasmsgs_setup(char *str) +{ + if (strcmp(str, "on") == 0) + full_rtas_msgs = 1; + else if (strcmp(str, "off") == 0) + full_rtas_msgs = 0; + + return 1; +} +__initcall(rtas_init); +__setup("surveillance=", surveillance_setup); +__setup("rtasmsgs=", rtasmsgs_setup); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index c0a3d918148a..f73d69143d35 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -589,9 +589,9 @@ struct machdep_calls __initdata pSeries_md = { .pcibios_fixup = pSeries_final_fixup, .pci_probe_mode = pSeries_pci_probe_mode, .irq_bus_setup = pSeries_irq_bus_setup, - .restart = rtas_fw_restart, - .power_off = rtas_fw_power_off, - .halt = rtas_fw_halt, + .restart = rtas_restart, + .power_off = rtas_power_off, + .halt = rtas_halt, .panic = rtas_os_term, .cpu_die = pSeries_mach_cpu_die, .get_boot_time = rtas_get_boot_time, diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 990df0905c87..74892ad032ba 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -29,19 +29,17 @@ ifneq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o endif -obj-$(CONFIG_PPC_PSERIES) += rtasd.o udbg_16550.o +obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o obj-$(CONFIG_KEXEC) += machine_kexec.o obj-$(CONFIG_EEH) += eeh.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o -obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ifneq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_MODULES) += ppc_ksyms.o endif obj-$(CONFIG_PPC_RTAS) += rtas_pci.o -obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c deleted file mode 100644 index 5bdd5b079d96..000000000000 --- a/arch/ppc64/kernel/rtas-proc.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * arch/ppc64/kernel/rtas-proc.c - * Copyright (C) 2000 Tilmann Bitterberg - * (tilmann@bitterberg.de) - * - * RTAS (Runtime Abstraction Services) stuff - * Intention is to provide a clean user interface - * to use the RTAS. - * - * TODO: - * Split off a header file and maybe move it to a different - * location. Write Documentation on what the /proc/rtas/ entries - * actually do. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include /* for ppc_md */ -#include -#include - -/* Token for Sensors */ -#define KEY_SWITCH 0x0001 -#define ENCLOSURE_SWITCH 0x0002 -#define THERMAL_SENSOR 0x0003 -#define LID_STATUS 0x0004 -#define POWER_SOURCE 0x0005 -#define BATTERY_VOLTAGE 0x0006 -#define BATTERY_REMAINING 0x0007 -#define BATTERY_PERCENTAGE 0x0008 -#define EPOW_SENSOR 0x0009 -#define BATTERY_CYCLESTATE 0x000a -#define BATTERY_CHARGING 0x000b - -/* IBM specific sensors */ -#define IBM_SURVEILLANCE 0x2328 /* 9000 */ -#define IBM_FANRPM 0x2329 /* 9001 */ -#define IBM_VOLTAGE 0x232a /* 9002 */ -#define IBM_DRCONNECTOR 0x232b /* 9003 */ -#define IBM_POWERSUPPLY 0x232c /* 9004 */ - -/* Status return values */ -#define SENSOR_CRITICAL_HIGH 13 -#define SENSOR_WARNING_HIGH 12 -#define SENSOR_NORMAL 11 -#define SENSOR_WARNING_LOW 10 -#define SENSOR_CRITICAL_LOW 9 -#define SENSOR_SUCCESS 0 -#define SENSOR_HW_ERROR -1 -#define SENSOR_BUSY -2 -#define SENSOR_NOT_EXIST -3 -#define SENSOR_DR_ENTITY -9000 - -/* Location Codes */ -#define LOC_SCSI_DEV_ADDR 'A' -#define LOC_SCSI_DEV_LOC 'B' -#define LOC_CPU 'C' -#define LOC_DISKETTE 'D' -#define LOC_ETHERNET 'E' -#define LOC_FAN 'F' -#define LOC_GRAPHICS 'G' -/* reserved / not used 'H' */ -#define LOC_IO_ADAPTER 'I' -/* reserved / not used 'J' */ -#define LOC_KEYBOARD 'K' -#define LOC_LCD 'L' -#define LOC_MEMORY 'M' -#define LOC_NV_MEMORY 'N' -#define LOC_MOUSE 'O' -#define LOC_PLANAR 'P' -#define LOC_OTHER_IO 'Q' -#define LOC_PARALLEL 'R' -#define LOC_SERIAL 'S' -#define LOC_DEAD_RING 'T' -#define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */ -#define LOC_VOLTAGE 'V' -#define LOC_SWITCH_ADAPTER 'W' -#define LOC_OTHER 'X' -#define LOC_FIRMWARE 'Y' -#define LOC_SCSI 'Z' - -/* Tokens for indicators */ -#define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/ -#define TONE_VOLUME 0x0002 /* 0 - 100 (%) */ -#define SYSTEM_POWER_STATE 0x0003 -#define WARNING_LIGHT 0x0004 -#define DISK_ACTIVITY_LIGHT 0x0005 -#define HEX_DISPLAY_UNIT 0x0006 -#define BATTERY_WARNING_TIME 0x0007 -#define CONDITION_CYCLE_REQUEST 0x0008 -#define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */ -#define DR_ACTION 0x2329 /* 9001 */ -#define DR_INDICATOR 0x232a /* 9002 */ -/* 9003 - 9004: Vendor specific */ -/* 9006 - 9999: Vendor specific */ - -/* other */ -#define MAX_SENSORS 17 /* I only know of 17 sensors */ -#define MAX_LINELENGTH 256 -#define SENSOR_PREFIX "ibm,sensor-" -#define cel_to_fahr(x) ((x*9/5)+32) - - -/* Globals */ -static struct rtas_sensors sensors; -static struct device_node *rtas_node = NULL; -static unsigned long power_on_time = 0; /* Save the time the user set */ -static char progress_led[MAX_LINELENGTH]; - -static unsigned long rtas_tone_frequency = 1000; -static unsigned long rtas_tone_volume = 0; - -/* ****************STRUCTS******************************************* */ -struct individual_sensor { - unsigned int token; - unsigned int quant; -}; - -struct rtas_sensors { - struct individual_sensor sensor[MAX_SENSORS]; - unsigned int quant; -}; - -/* ****************************************************************** */ -/* Declarations */ -static int ppc_rtas_sensors_show(struct seq_file *m, void *v); -static int ppc_rtas_clock_show(struct seq_file *m, void *v); -static ssize_t ppc_rtas_clock_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ppc_rtas_progress_show(struct seq_file *m, void *v); -static ssize_t ppc_rtas_progress_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ppc_rtas_poweron_show(struct seq_file *m, void *v); -static ssize_t ppc_rtas_poweron_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); - -static ssize_t ppc_rtas_tone_freq_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v); -static ssize_t ppc_rtas_tone_volume_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v); -static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v); - -static int sensors_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_sensors_show, NULL); -} - -struct file_operations ppc_rtas_sensors_operations = { - .open = sensors_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int poweron_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_poweron_show, NULL); -} - -struct file_operations ppc_rtas_poweron_operations = { - .open = poweron_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_poweron_write, - .release = single_release, -}; - -static int progress_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_progress_show, NULL); -} - -struct file_operations ppc_rtas_progress_operations = { - .open = progress_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_progress_write, - .release = single_release, -}; - -static int clock_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_clock_show, NULL); -} - -struct file_operations ppc_rtas_clock_operations = { - .open = clock_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_clock_write, - .release = single_release, -}; - -static int tone_freq_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_tone_freq_show, NULL); -} - -struct file_operations ppc_rtas_tone_freq_operations = { - .open = tone_freq_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_tone_freq_write, - .release = single_release, -}; - -static int tone_volume_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_tone_volume_show, NULL); -} - -struct file_operations ppc_rtas_tone_volume_operations = { - .open = tone_volume_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_tone_volume_write, - .release = single_release, -}; - -static int rmo_buf_open(struct inode *inode, struct file *file) -{ - return single_open(file, ppc_rtas_rmo_buf_show, NULL); -} - -struct file_operations ppc_rtas_rmo_buf_ops = { - .open = rmo_buf_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int ppc_rtas_find_all_sensors(void); -static void ppc_rtas_process_sensor(struct seq_file *m, - struct individual_sensor *s, int state, int error, char *loc); -static char *ppc_rtas_process_error(int error); -static void get_location_code(struct seq_file *m, - struct individual_sensor *s, char *loc); -static void check_location_string(struct seq_file *m, char *c); -static void check_location(struct seq_file *m, char *c); - -static int __init proc_rtas_init(void) -{ - struct proc_dir_entry *entry; - - if (!(systemcfg->platform & PLATFORM_PSERIES)) - return 1; - - rtas_node = of_find_node_by_name(NULL, "rtas"); - if (rtas_node == NULL) - return 1; - - entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_progress_operations; - - entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_clock_operations; - - entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_poweron_operations; - - entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_sensors_operations; - - entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, - NULL); - if (entry) - entry->proc_fops = &ppc_rtas_tone_freq_operations; - - entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_tone_volume_operations; - - entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_rmo_buf_ops; - - return 0; -} - -__initcall(proc_rtas_init); - -static int parse_number(const char __user *p, size_t count, unsigned long *val) -{ - char buf[40]; - char *end; - - if (count > 39) - return -EINVAL; - - if (copy_from_user(buf, p, count)) - return -EFAULT; - - buf[count] = 0; - - *val = simple_strtoul(buf, &end, 10); - if (*end && *end != '\n') - return -EINVAL; - - return 0; -} - -/* ****************************************************************** */ -/* POWER-ON-TIME */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_poweron_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct rtc_time tm; - unsigned long nowtime; - int error = parse_number(buf, count, &nowtime); - if (error) - return error; - - power_on_time = nowtime; /* save the time */ - - to_tm(nowtime, &tm); - - error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); - if (error) - printk(KERN_WARNING "error: setting poweron time returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static int ppc_rtas_poweron_show(struct seq_file *m, void *v) -{ - if (power_on_time == 0) - seq_printf(m, "Power on time not set\n"); - else - seq_printf(m, "%lu\n",power_on_time); - return 0; -} - -/* ****************************************************************** */ -/* PROGRESS */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_progress_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long hex; - - if (count >= MAX_LINELENGTH) - count = MAX_LINELENGTH -1; - if (copy_from_user(progress_led, buf, count)) { /* save the string */ - return -EFAULT; - } - progress_led[count] = 0; - - /* Lets see if the user passed hexdigits */ - hex = simple_strtoul(progress_led, NULL, 10); - - rtas_progress ((char *)progress_led, hex); - return count; - - /* clear the line */ - /* rtas_progress(" ", 0xffff);*/ -} -/* ****************************************************************** */ -static int ppc_rtas_progress_show(struct seq_file *m, void *v) -{ - if (progress_led) - seq_printf(m, "%s\n", progress_led); - return 0; -} - -/* ****************************************************************** */ -/* CLOCK */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_clock_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct rtc_time tm; - unsigned long nowtime; - int error = parse_number(buf, count, &nowtime); - if (error) - return error; - - to_tm(nowtime, &tm); - error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, 0); - if (error) - printk(KERN_WARNING "error: setting the clock returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static int ppc_rtas_clock_show(struct seq_file *m, void *v) -{ - int ret[8]; - int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); - - if (error) { - printk(KERN_WARNING "error: reading the clock returned: %s\n", - ppc_rtas_process_error(error)); - seq_printf(m, "0"); - } else { - unsigned int year, mon, day, hour, min, sec; - year = ret[0]; mon = ret[1]; day = ret[2]; - hour = ret[3]; min = ret[4]; sec = ret[5]; - seq_printf(m, "%lu\n", - mktime(year, mon, day, hour, min, sec)); - } - return 0; -} - -/* ****************************************************************** */ -/* SENSOR STUFF */ -/* ****************************************************************** */ -static int ppc_rtas_sensors_show(struct seq_file *m, void *v) -{ - int i,j; - int state, error; - int get_sensor_state = rtas_token("get-sensor-state"); - - seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n"); - seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n"); - seq_printf(m, "********************************************************\n"); - - if (ppc_rtas_find_all_sensors() != 0) { - seq_printf(m, "\nNo sensors are available\n"); - return 0; - } - - for (i=0; itoken); - loc = (char *) get_property(rtas_node, rstr, &llen); - - /* A sensor may have multiple instances */ - for (j = 0, offs = 0; j <= p->quant; j++) { - error = rtas_call(get_sensor_state, 2, 2, &state, - p->token, j); - - ppc_rtas_process_sensor(m, p, state, error, loc); - seq_putc(m, '\n'); - if (loc) { - offs += strlen(loc) + 1; - loc += strlen(loc) + 1; - if (offs >= llen) - loc = NULL; - } - } - } - return 0; -} - -/* ****************************************************************** */ - -static int ppc_rtas_find_all_sensors(void) -{ - unsigned int *utmp; - int len, i; - - utmp = (unsigned int *) get_property(rtas_node, "rtas-sensors", &len); - if (utmp == NULL) { - printk (KERN_ERR "error: could not get rtas-sensors\n"); - return 1; - } - - sensors.quant = len / 8; /* int + int */ - - for (i=0; itoken) { - case KEY_SWITCH: - seq_printf(m, "Key switch:\t"); - num_states = sizeof(key_switch) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", key_switch[state]); - have_strings = 1; - } - break; - case ENCLOSURE_SWITCH: - seq_printf(m, "Enclosure switch:\t"); - num_states = sizeof(enclosure_switch) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - enclosure_switch[state]); - have_strings = 1; - } - break; - case THERMAL_SENSOR: - seq_printf(m, "Temp. (C/F):\t"); - temperature = 1; - break; - case LID_STATUS: - seq_printf(m, "Lid status:\t"); - num_states = sizeof(lid_status) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", lid_status[state]); - have_strings = 1; - } - break; - case POWER_SOURCE: - seq_printf(m, "Power source:\t"); - num_states = sizeof(power_source) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - power_source[state]); - have_strings = 1; - } - break; - case BATTERY_VOLTAGE: - seq_printf(m, "Battery voltage:\t"); - break; - case BATTERY_REMAINING: - seq_printf(m, "Battery remaining:\t"); - num_states = sizeof(battery_remaining) / sizeof(char *); - if (state < num_states) - { - seq_printf(m, "%s\t", - battery_remaining[state]); - have_strings = 1; - } - break; - case BATTERY_PERCENTAGE: - seq_printf(m, "Battery percentage:\t"); - break; - case EPOW_SENSOR: - seq_printf(m, "EPOW Sensor:\t"); - num_states = sizeof(epow_sensor) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", epow_sensor[state]); - have_strings = 1; - } - break; - case BATTERY_CYCLESTATE: - seq_printf(m, "Battery cyclestate:\t"); - num_states = sizeof(battery_cyclestate) / - sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - battery_cyclestate[state]); - have_strings = 1; - } - break; - case BATTERY_CHARGING: - seq_printf(m, "Battery Charging:\t"); - num_states = sizeof(battery_charging) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - battery_charging[state]); - have_strings = 1; - } - break; - case IBM_SURVEILLANCE: - seq_printf(m, "Surveillance:\t"); - break; - case IBM_FANRPM: - seq_printf(m, "Fan (rpm):\t"); - break; - case IBM_VOLTAGE: - seq_printf(m, "Voltage (mv):\t"); - break; - case IBM_DRCONNECTOR: - seq_printf(m, "DR connector:\t"); - num_states = sizeof(ibm_drconnector) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - ibm_drconnector[state]); - have_strings = 1; - } - break; - case IBM_POWERSUPPLY: - seq_printf(m, "Powersupply:\t"); - break; - default: - seq_printf(m, "Unknown sensor (type %d), ignoring it\n", - s->token); - unknown = 1; - have_strings = 1; - break; - } - if (have_strings == 0) { - if (temperature) { - seq_printf(m, "%4d /%4d\t", state, cel_to_fahr(state)); - } else - seq_printf(m, "%10d\t", state); - } - if (unknown == 0) { - seq_printf(m, "%s\t", ppc_rtas_process_error(error)); - get_location_code(m, s, loc); - } -} - -/* ****************************************************************** */ - -static void check_location(struct seq_file *m, char *c) -{ - switch (c[0]) { - case LOC_PLANAR: - seq_printf(m, "Planar #%c", c[1]); - break; - case LOC_CPU: - seq_printf(m, "CPU #%c", c[1]); - break; - case LOC_FAN: - seq_printf(m, "Fan #%c", c[1]); - break; - case LOC_RACKMOUNTED: - seq_printf(m, "Rack #%c", c[1]); - break; - case LOC_VOLTAGE: - seq_printf(m, "Voltage #%c", c[1]); - break; - case LOC_LCD: - seq_printf(m, "LCD #%c", c[1]); - break; - case '.': - seq_printf(m, "- %c", c[1]); - break; - default: - seq_printf(m, "Unknown location"); - break; - } -} - - -/* ****************************************************************** */ -/* - * Format: - * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ] - * the '.' may be an abbrevation - */ -static void check_location_string(struct seq_file *m, char *c) -{ - while (*c) { - if (isalpha(*c) || *c == '.') - check_location(m, c); - else if (*c == '/' || *c == '-') - seq_printf(m, " at "); - c++; - } -} - - -/* ****************************************************************** */ - -static void get_location_code(struct seq_file *m, struct individual_sensor *s, char *loc) -{ - if (!loc || !*loc) { - seq_printf(m, "---");/* does not have a location */ - } else { - check_location_string(m, loc); - } - seq_putc(m, ' '); -} -/* ****************************************************************** */ -/* INDICATORS - Tone Frequency */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_freq_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long freq; - int error = parse_number(buf, count, &freq); - if (error) - return error; - - rtas_tone_frequency = freq; /* save it for later */ - error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, - TONE_FREQUENCY, 0, freq); - if (error) - printk(KERN_WARNING "error: setting tone frequency returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%lu\n", rtas_tone_frequency); - return 0; -} -/* ****************************************************************** */ -/* INDICATORS - Tone Volume */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_volume_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long volume; - int error = parse_number(buf, count, &volume); - if (error) - return error; - - if (volume > 100) - volume = 100; - - rtas_tone_volume = volume; /* save it for later */ - error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, - TONE_VOLUME, 0, volume); - if (error) - printk(KERN_WARNING "error: setting tone volume returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%lu\n", rtas_tone_volume); - return 0; -} - -#define RMO_READ_BUF_MAX 30 - -/* RTAS Userspace access */ -static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%016lx %x\n", rtas_rmo_buf, RTAS_RMOBUF_MAX); - return 0; -} diff --git a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c deleted file mode 100644 index 923e2e201a70..000000000000 --- a/arch/ppc64/kernel/rtas_flash.c +++ /dev/null @@ -1,725 +0,0 @@ -/* - * c 2001 PPC 64 Team, IBM Corp - * - * 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. - * - * /proc/ppc64/rtas/firmware_flash interface - * - * This file implements a firmware_flash interface to pump a firmware - * image into the kernel. At reboot time rtas_restart() will see the - * firmware image and flash it as it reboots (see rtas.c). - */ - -#include -#include -#include -#include -#include -#include - -#define MODULE_VERS "1.0" -#define MODULE_NAME "rtas_flash" - -#define FIRMWARE_FLASH_NAME "firmware_flash" -#define FIRMWARE_UPDATE_NAME "firmware_update" -#define MANAGE_FLASH_NAME "manage_flash" -#define VALIDATE_FLASH_NAME "validate_flash" - -/* General RTAS Status Codes */ -#define RTAS_RC_SUCCESS 0 -#define RTAS_RC_HW_ERR -1 -#define RTAS_RC_BUSY -2 - -/* Flash image status values */ -#define FLASH_AUTH -9002 /* RTAS Not Service Authority Partition */ -#define FLASH_NO_OP -1099 /* No operation initiated by user */ -#define FLASH_IMG_SHORT -1005 /* Flash image shorter than expected */ -#define FLASH_IMG_BAD_LEN -1004 /* Bad length value in flash list block */ -#define FLASH_IMG_NULL_DATA -1003 /* Bad data value in flash list block */ -#define FLASH_IMG_READY 0 /* Firmware img ready for flash on reboot */ - -/* Manage image status values */ -#define MANAGE_AUTH -9002 /* RTAS Not Service Authority Partition */ -#define MANAGE_ACTIVE_ERR -9001 /* RTAS Cannot Overwrite Active Img */ -#define MANAGE_NO_OP -1099 /* No operation initiated by user */ -#define MANAGE_PARAM_ERR -3 /* RTAS Parameter Error */ -#define MANAGE_HW_ERR -1 /* RTAS Hardware Error */ - -/* Validate image status values */ -#define VALIDATE_AUTH -9002 /* RTAS Not Service Authority Partition */ -#define VALIDATE_NO_OP -1099 /* No operation initiated by the user */ -#define VALIDATE_INCOMPLETE -1002 /* User copied < VALIDATE_BUF_SIZE */ -#define VALIDATE_READY -1001 /* Firmware image ready for validation */ -#define VALIDATE_PARAM_ERR -3 /* RTAS Parameter Error */ -#define VALIDATE_HW_ERR -1 /* RTAS Hardware Error */ -#define VALIDATE_TMP_UPDATE 0 /* Validate Return Status */ -#define VALIDATE_FLASH_AUTH 1 /* Validate Return Status */ -#define VALIDATE_INVALID_IMG 2 /* Validate Return Status */ -#define VALIDATE_CUR_UNKNOWN 3 /* Validate Return Status */ -#define VALIDATE_TMP_COMMIT_DL 4 /* Validate Return Status */ -#define VALIDATE_TMP_COMMIT 5 /* Validate Return Status */ -#define VALIDATE_TMP_UPDATE_DL 6 /* Validate Return Status */ - -/* ibm,manage-flash-image operation tokens */ -#define RTAS_REJECT_TMP_IMG 0 -#define RTAS_COMMIT_TMP_IMG 1 - -/* Array sizes */ -#define VALIDATE_BUF_SIZE 4096 -#define RTAS_MSG_MAXLEN 64 - -/* Local copy of the flash block list. - * We only allow one open of the flash proc file and create this - * list as we go. This list will be put in the kernel's - * rtas_firmware_flash_list global var once it is fully read. - * - * For convenience as we build the list we use virtual addrs, - * we do not fill in the version number, and the length field - * is treated as the number of entries currently in the block - * (i.e. not a byte count). This is all fixed on release. - */ - -/* Status int must be first member of struct */ -struct rtas_update_flash_t -{ - int status; /* Flash update status */ - struct flash_block_list *flist; /* Local copy of flash block list */ -}; - -/* Status int must be first member of struct */ -struct rtas_manage_flash_t -{ - int status; /* Returned status */ - unsigned int op; /* Reject or commit image */ -}; - -/* Status int must be first member of struct */ -struct rtas_validate_flash_t -{ - int status; /* Returned status */ - char buf[VALIDATE_BUF_SIZE]; /* Candidate image buffer */ - unsigned int buf_size; /* Size of image buf */ - unsigned int update_results; /* Update results token */ -}; - -static DEFINE_SPINLOCK(flash_file_open_lock); -static struct proc_dir_entry *firmware_flash_pde; -static struct proc_dir_entry *firmware_update_pde; -static struct proc_dir_entry *validate_pde; -static struct proc_dir_entry *manage_pde; - -/* Do simple sanity checks on the flash image. */ -static int flash_list_valid(struct flash_block_list *flist) -{ - struct flash_block_list *f; - int i; - unsigned long block_size, image_size; - - /* Paranoid self test here. We also collect the image size. */ - image_size = 0; - for (f = flist; f; f = f->next) { - for (i = 0; i < f->num_blocks; i++) { - if (f->blocks[i].data == NULL) { - return FLASH_IMG_NULL_DATA; - } - block_size = f->blocks[i].length; - if (block_size <= 0 || block_size > PAGE_SIZE) { - return FLASH_IMG_BAD_LEN; - } - image_size += block_size; - } - } - - if (image_size < (256 << 10)) { - if (image_size < 2) - return FLASH_NO_OP; - } - - printk(KERN_INFO "FLASH: flash image with %ld bytes stored for hardware flash on reboot\n", image_size); - - return FLASH_IMG_READY; -} - -static void free_flash_list(struct flash_block_list *f) -{ - struct flash_block_list *next; - int i; - - while (f) { - for (i = 0; i < f->num_blocks; i++) - free_page((unsigned long)(f->blocks[i].data)); - next = f->next; - free_page((unsigned long)f); - f = next; - } -} - -static int rtas_flash_release(struct inode *inode, struct file *file) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_update_flash_t *uf; - - uf = (struct rtas_update_flash_t *) dp->data; - if (uf->flist) { - /* File was opened in write mode for a new flash attempt */ - /* Clear saved list */ - if (rtas_firmware_flash_list.next) { - free_flash_list(rtas_firmware_flash_list.next); - rtas_firmware_flash_list.next = NULL; - } - - if (uf->status != FLASH_AUTH) - uf->status = flash_list_valid(uf->flist); - - if (uf->status == FLASH_IMG_READY) - rtas_firmware_flash_list.next = uf->flist; - else - free_flash_list(uf->flist); - - uf->flist = NULL; - } - - atomic_dec(&dp->count); - return 0; -} - -static void get_flash_status_msg(int status, char *buf) -{ - char *msg; - - switch (status) { - case FLASH_AUTH: - msg = "error: this partition does not have service authority\n"; - break; - case FLASH_NO_OP: - msg = "info: no firmware image for flash\n"; - break; - case FLASH_IMG_SHORT: - msg = "error: flash image short\n"; - break; - case FLASH_IMG_BAD_LEN: - msg = "error: internal error bad length\n"; - break; - case FLASH_IMG_NULL_DATA: - msg = "error: internal error null data\n"; - break; - case FLASH_IMG_READY: - msg = "ready: firmware image ready for flash on reboot\n"; - break; - default: - sprintf(buf, "error: unexpected status value %d\n", status); - return; - } - - strcpy(buf, msg); -} - -/* Reading the proc file will show status (not the firmware contents) */ -static ssize_t rtas_flash_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_update_flash_t *uf; - char msg[RTAS_MSG_MAXLEN]; - int msglen; - - uf = (struct rtas_update_flash_t *) dp->data; - - if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) { - get_flash_status_msg(uf->status, msg); - } else { /* FIRMWARE_UPDATE_NAME */ - sprintf(msg, "%d\n", uf->status); - } - msglen = strlen(msg); - if (msglen > count) - msglen = count; - - if (ppos && *ppos != 0) - return 0; /* be cheap */ - - if (!access_ok(VERIFY_WRITE, buf, msglen)) - return -EINVAL; - - if (copy_to_user(buf, msg, msglen)) - return -EFAULT; - - if (ppos) - *ppos = msglen; - return msglen; -} - -/* We could be much more efficient here. But to keep this function - * simple we allocate a page to the block list no matter how small the - * count is. If the system is low on memory it will be just as well - * that we fail.... - */ -static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, - size_t count, loff_t *off) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_update_flash_t *uf; - char *p; - int next_free; - struct flash_block_list *fl; - - uf = (struct rtas_update_flash_t *) dp->data; - - if (uf->status == FLASH_AUTH || count == 0) - return count; /* discard data */ - - /* In the case that the image is not ready for flashing, the memory - * allocated for the block list will be freed upon the release of the - * proc file - */ - if (uf->flist == NULL) { - uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); - if (!uf->flist) - return -ENOMEM; - } - - fl = uf->flist; - while (fl->next) - fl = fl->next; /* seek to last block_list for append */ - next_free = fl->num_blocks; - if (next_free == FLASH_BLOCKS_PER_NODE) { - /* Need to allocate another block_list */ - fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); - if (!fl->next) - return -ENOMEM; - fl = fl->next; - next_free = 0; - } - - if (count > PAGE_SIZE) - count = PAGE_SIZE; - p = (char *)get_zeroed_page(GFP_KERNEL); - if (!p) - return -ENOMEM; - - if(copy_from_user(p, buffer, count)) { - free_page((unsigned long)p); - return -EFAULT; - } - fl->blocks[next_free].data = p; - fl->blocks[next_free].length = count; - fl->num_blocks++; - - return count; -} - -static int rtas_excl_open(struct inode *inode, struct file *file) -{ - struct proc_dir_entry *dp = PDE(inode); - - /* Enforce exclusive open with use count of PDE */ - spin_lock(&flash_file_open_lock); - if (atomic_read(&dp->count) > 1) { - spin_unlock(&flash_file_open_lock); - return -EBUSY; - } - - atomic_inc(&dp->count); - spin_unlock(&flash_file_open_lock); - - return 0; -} - -static int rtas_excl_release(struct inode *inode, struct file *file) -{ - struct proc_dir_entry *dp = PDE(inode); - - atomic_dec(&dp->count); - - return 0; -} - -static void manage_flash(struct rtas_manage_flash_t *args_buf) -{ - unsigned int wait_time; - s32 rc; - - while (1) { - rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, - 1, NULL, args_buf->op); - if (rc == RTAS_RC_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } - - args_buf->status = rc; -} - -static ssize_t manage_flash_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_manage_flash_t *args_buf; - char msg[RTAS_MSG_MAXLEN]; - int msglen; - - args_buf = (struct rtas_manage_flash_t *) dp->data; - if (args_buf == NULL) - return 0; - - msglen = sprintf(msg, "%d\n", args_buf->status); - if (msglen > count) - msglen = count; - - if (ppos && *ppos != 0) - return 0; /* be cheap */ - - if (!access_ok(VERIFY_WRITE, buf, msglen)) - return -EINVAL; - - if (copy_to_user(buf, msg, msglen)) - return -EFAULT; - - if (ppos) - *ppos = msglen; - return msglen; -} - -static ssize_t manage_flash_write(struct file *file, const char __user *buf, - size_t count, loff_t *off) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_manage_flash_t *args_buf; - const char reject_str[] = "0"; - const char commit_str[] = "1"; - char stkbuf[10]; - int op; - - args_buf = (struct rtas_manage_flash_t *) dp->data; - if ((args_buf->status == MANAGE_AUTH) || (count == 0)) - return count; - - op = -1; - if (buf) { - if (count > 9) count = 9; - if (copy_from_user (stkbuf, buf, count)) { - return -EFAULT; - } - if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0) - op = RTAS_REJECT_TMP_IMG; - else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0) - op = RTAS_COMMIT_TMP_IMG; - } - - if (op == -1) /* buf is empty, or contains invalid string */ - return -EINVAL; - - args_buf->op = op; - manage_flash(args_buf); - - return count; -} - -static void validate_flash(struct rtas_validate_flash_t *args_buf) -{ - int token = rtas_token("ibm,validate-flash-image"); - unsigned int wait_time; - int update_results; - s32 rc; - - rc = 0; - while(1) { - spin_lock(&rtas_data_buf_lock); - memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); - rc = rtas_call(token, 2, 2, &update_results, - (u32) __pa(rtas_data_buf), args_buf->buf_size); - memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); - spin_unlock(&rtas_data_buf_lock); - - if (rc == RTAS_RC_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } - - args_buf->status = rc; - args_buf->update_results = update_results; -} - -static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, - char *msg) -{ - int n; - - if (args_buf->status >= VALIDATE_TMP_UPDATE) { - n = sprintf(msg, "%d\n", args_buf->update_results); - if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || - (args_buf->update_results == VALIDATE_TMP_UPDATE)) - n += sprintf(msg + n, "%s\n", args_buf->buf); - } else { - n = sprintf(msg, "%d\n", args_buf->status); - } - return n; -} - -static ssize_t validate_flash_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_validate_flash_t *args_buf; - char msg[RTAS_MSG_MAXLEN]; - int msglen; - - args_buf = (struct rtas_validate_flash_t *) dp->data; - - if (ppos && *ppos != 0) - return 0; /* be cheap */ - - msglen = get_validate_flash_msg(args_buf, msg); - if (msglen > count) - msglen = count; - - if (!access_ok(VERIFY_WRITE, buf, msglen)) - return -EINVAL; - - if (copy_to_user(buf, msg, msglen)) - return -EFAULT; - - if (ppos) - *ppos = msglen; - return msglen; -} - -static ssize_t validate_flash_write(struct file *file, const char __user *buf, - size_t count, loff_t *off) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_validate_flash_t *args_buf; - int rc; - - args_buf = (struct rtas_validate_flash_t *) dp->data; - - if (dp->data == NULL) { - dp->data = kmalloc(sizeof(struct rtas_validate_flash_t), - GFP_KERNEL); - if (dp->data == NULL) - return -ENOMEM; - } - - /* We are only interested in the first 4K of the - * candidate image */ - if ((*off >= VALIDATE_BUF_SIZE) || - (args_buf->status == VALIDATE_AUTH)) { - *off += count; - return count; - } - - if (*off + count >= VALIDATE_BUF_SIZE) { - count = VALIDATE_BUF_SIZE - *off; - args_buf->status = VALIDATE_READY; - } else { - args_buf->status = VALIDATE_INCOMPLETE; - } - - if (!access_ok(VERIFY_READ, buf, count)) { - rc = -EFAULT; - goto done; - } - if (copy_from_user(args_buf->buf + *off, buf, count)) { - rc = -EFAULT; - goto done; - } - - *off += count; - rc = count; -done: - if (rc < 0) { - kfree(dp->data); - dp->data = NULL; - } - return rc; -} - -static int validate_flash_release(struct inode *inode, struct file *file) -{ - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - struct rtas_validate_flash_t *args_buf; - - args_buf = (struct rtas_validate_flash_t *) dp->data; - - if (args_buf->status == VALIDATE_READY) { - args_buf->buf_size = VALIDATE_BUF_SIZE; - validate_flash(args_buf); - } - - /* The matching atomic_inc was in rtas_excl_open() */ - atomic_dec(&dp->count); - - return 0; -} - -static void remove_flash_pde(struct proc_dir_entry *dp) -{ - if (dp) { - if (dp->data != NULL) - kfree(dp->data); - dp->owner = NULL; - remove_proc_entry(dp->name, dp->parent); - } -} - -static int initialize_flash_pde_data(const char *rtas_call_name, - size_t buf_size, - struct proc_dir_entry *dp) -{ - int *status; - int token; - - dp->data = kmalloc(buf_size, GFP_KERNEL); - if (dp->data == NULL) { - remove_flash_pde(dp); - return -ENOMEM; - } - - memset(dp->data, 0, buf_size); - - /* - * This code assumes that the status int is the first member of the - * struct - */ - status = (int *) dp->data; - token = rtas_token(rtas_call_name); - if (token == RTAS_UNKNOWN_SERVICE) - *status = FLASH_AUTH; - else - *status = FLASH_NO_OP; - - return 0; -} - -static struct proc_dir_entry *create_flash_pde(const char *filename, - struct file_operations *fops) -{ - struct proc_dir_entry *ent = NULL; - - ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL); - if (ent != NULL) { - ent->nlink = 1; - ent->proc_fops = fops; - ent->owner = THIS_MODULE; - } - - return ent; -} - -static struct file_operations rtas_flash_operations = { - .read = rtas_flash_read, - .write = rtas_flash_write, - .open = rtas_excl_open, - .release = rtas_flash_release, -}; - -static struct file_operations manage_flash_operations = { - .read = manage_flash_read, - .write = manage_flash_write, - .open = rtas_excl_open, - .release = rtas_excl_release, -}; - -static struct file_operations validate_flash_operations = { - .read = validate_flash_read, - .write = validate_flash_write, - .open = rtas_excl_open, - .release = validate_flash_release, -}; - -int __init rtas_flash_init(void) -{ - int rc; - - if (rtas_token("ibm,update-flash-64-and-reboot") == - RTAS_UNKNOWN_SERVICE) { - printk(KERN_ERR "rtas_flash: no firmware flash support\n"); - return 1; - } - - firmware_flash_pde = create_flash_pde("ppc64/rtas/" - FIRMWARE_FLASH_NAME, - &rtas_flash_operations); - if (firmware_flash_pde == NULL) { - rc = -ENOMEM; - goto cleanup; - } - - rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", - sizeof(struct rtas_update_flash_t), - firmware_flash_pde); - if (rc != 0) - goto cleanup; - - firmware_update_pde = create_flash_pde("ppc64/rtas/" - FIRMWARE_UPDATE_NAME, - &rtas_flash_operations); - if (firmware_update_pde == NULL) { - rc = -ENOMEM; - goto cleanup; - } - - rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", - sizeof(struct rtas_update_flash_t), - firmware_update_pde); - if (rc != 0) - goto cleanup; - - validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME, - &validate_flash_operations); - if (validate_pde == NULL) { - rc = -ENOMEM; - goto cleanup; - } - - rc = initialize_flash_pde_data("ibm,validate-flash-image", - sizeof(struct rtas_validate_flash_t), - validate_pde); - if (rc != 0) - goto cleanup; - - manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME, - &manage_flash_operations); - if (manage_pde == NULL) { - rc = -ENOMEM; - goto cleanup; - } - - rc = initialize_flash_pde_data("ibm,manage-flash-image", - sizeof(struct rtas_manage_flash_t), - manage_pde); - if (rc != 0) - goto cleanup; - - return 0; - -cleanup: - remove_flash_pde(firmware_flash_pde); - remove_flash_pde(firmware_update_pde); - remove_flash_pde(validate_pde); - remove_flash_pde(manage_pde); - - return rc; -} - -void __exit rtas_flash_cleanup(void) -{ - remove_flash_pde(firmware_flash_pde); - remove_flash_pde(firmware_update_pde); - remove_flash_pde(validate_pde); - remove_flash_pde(manage_pde); -} - -module_init(rtas_flash_init); -module_exit(rtas_flash_cleanup); -MODULE_LICENSE("GPL"); diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c deleted file mode 100644 index e26b0420b6dd..000000000000 --- a/arch/ppc64/kernel/rtasd.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (C) 2001 Anton Blanchard , IBM - * - * 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. - * - * Communication to userspace based on kernel/printk.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define DEBUG(A...) printk(KERN_ERR A) -#else -#define DEBUG(A...) -#endif - -static DEFINE_SPINLOCK(rtasd_log_lock); - -DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); - -static char *rtas_log_buf; -static unsigned long rtas_log_start; -static unsigned long rtas_log_size; - -static int surveillance_timeout = -1; -static unsigned int rtas_event_scan_rate; -static unsigned int rtas_error_log_max; -static unsigned int rtas_error_log_buffer_max; - -static int full_rtas_msgs = 0; - -extern int no_logging; - -volatile int error_log_cnt = 0; - -/* - * Since we use 32 bit RTAS, the physical address of this must be below - * 4G or else bad things happen. Allocate this in the kernel data and - * make it big enough. - */ -static unsigned char logdata[RTAS_ERROR_LOG_MAX]; - -static int get_eventscan_parms(void); - -static char *rtas_type[] = { - "Unknown", "Retry", "TCE Error", "Internal Device Failure", - "Timeout", "Data Parity", "Address Parity", "Cache Parity", - "Address Invalid", "ECC Uncorrected", "ECC Corrupted", -}; - -static char *rtas_event_type(int type) -{ - if ((type > 0) && (type < 11)) - return rtas_type[type]; - - switch (type) { - case RTAS_TYPE_EPOW: - return "EPOW"; - case RTAS_TYPE_PLATFORM: - return "Platform Error"; - case RTAS_TYPE_IO: - return "I/O Event"; - case RTAS_TYPE_INFO: - return "Platform Information Event"; - case RTAS_TYPE_DEALLOC: - return "Resource Deallocation Event"; - case RTAS_TYPE_DUMP: - return "Dump Notification Event"; - } - - return rtas_type[0]; -} - -/* To see this info, grep RTAS /var/log/messages and each entry - * will be collected together with obvious begin/end. - * There will be a unique identifier on the begin and end lines. - * This will persist across reboots. - * - * format of error logs returned from RTAS: - * bytes (size) : contents - * -------------------------------------------------------- - * 0-7 (8) : rtas_error_log - * 8-47 (40) : extended info - * 48-51 (4) : vendor id - * 52-1023 (vendor specific) : location code and debug data - */ -static void printk_log_rtas(char *buf, int len) -{ - - int i,j,n = 0; - int perline = 16; - char buffer[64]; - char * str = "RTAS event"; - - if (full_rtas_msgs) { - printk(RTAS_DEBUG "%d -------- %s begin --------\n", - error_log_cnt, str); - - /* - * Print perline bytes on each line, each line will start - * with RTAS and a changing number, so syslogd will - * print lines that are otherwise the same. Separate every - * 4 bytes with a space. - */ - for (i = 0; i < len; i++) { - j = i % perline; - if (j == 0) { - memset(buffer, 0, sizeof(buffer)); - n = sprintf(buffer, "RTAS %d:", i/perline); - } - - if ((i % 4) == 0) - n += sprintf(buffer+n, " "); - - n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]); - - if (j == (perline-1)) - printk(KERN_DEBUG "%s\n", buffer); - } - if ((i % perline) != 0) - printk(KERN_DEBUG "%s\n", buffer); - - printk(RTAS_DEBUG "%d -------- %s end ----------\n", - error_log_cnt, str); - } else { - struct rtas_error_log *errlog = (struct rtas_error_log *)buf; - - printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n", - error_log_cnt, rtas_event_type(errlog->type), - errlog->severity); - } -} - -static int log_rtas_len(char * buf) -{ - int len; - struct rtas_error_log *err; - - /* rtas fixed header */ - len = 8; - err = (struct rtas_error_log *)buf; - if (err->extended_log_length) { - - /* extended header */ - len += err->extended_log_length; - } - - if (rtas_error_log_max == 0) { - get_eventscan_parms(); - } - if (len > rtas_error_log_max) - len = rtas_error_log_max; - - return len; -} - -/* - * First write to nvram, if fatal error, that is the only - * place we log the info. The error will be picked up - * on the next reboot by rtasd. If not fatal, run the - * method for the type of error. Currently, only RTAS - * errors have methods implemented, but in the future - * there might be a need to store data in nvram before a - * call to panic(). - * - * XXX We write to nvram periodically, to indicate error has - * been written and sync'd, but there is a possibility - * that if we don't shutdown correctly, a duplicate error - * record will be created on next reboot. - */ -void pSeries_log_error(char *buf, unsigned int err_type, int fatal) -{ - unsigned long offset; - unsigned long s; - int len = 0; - - DEBUG("logging event\n"); - if (buf == NULL) - return; - - spin_lock_irqsave(&rtasd_log_lock, s); - - /* get length and increase count */ - switch (err_type & ERR_TYPE_MASK) { - case ERR_TYPE_RTAS_LOG: - len = log_rtas_len(buf); - if (!(err_type & ERR_FLAG_BOOT)) - error_log_cnt++; - break; - case ERR_TYPE_KERNEL_PANIC: - default: - spin_unlock_irqrestore(&rtasd_log_lock, s); - return; - } - - /* Write error to NVRAM */ - if (!no_logging && !(err_type & ERR_FLAG_BOOT)) - nvram_write_error_log(buf, len, err_type); - - /* - * rtas errors can occur during boot, and we do want to capture - * those somewhere, even if nvram isn't ready (why not?), and even - * if rtasd isn't ready. Put them into the boot log, at least. - */ - if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG) - printk_log_rtas(buf, len); - - /* Check to see if we need to or have stopped logging */ - if (fatal || no_logging) { - no_logging = 1; - spin_unlock_irqrestore(&rtasd_log_lock, s); - return; - } - - /* call type specific method for error */ - switch (err_type & ERR_TYPE_MASK) { - case ERR_TYPE_RTAS_LOG: - offset = rtas_error_log_buffer_max * - ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); - - /* First copy over sequence number */ - memcpy(&rtas_log_buf[offset], (void *) &error_log_cnt, sizeof(int)); - - /* Second copy over error log data */ - offset += sizeof(int); - memcpy(&rtas_log_buf[offset], buf, len); - - if (rtas_log_size < LOG_NUMBER) - rtas_log_size += 1; - else - rtas_log_start += 1; - - spin_unlock_irqrestore(&rtasd_log_lock, s); - wake_up_interruptible(&rtas_log_wait); - break; - case ERR_TYPE_KERNEL_PANIC: - default: - spin_unlock_irqrestore(&rtasd_log_lock, s); - return; - } - -} - - -static int rtas_log_open(struct inode * inode, struct file * file) -{ - return 0; -} - -static int rtas_log_release(struct inode * inode, struct file * file) -{ - return 0; -} - -/* This will check if all events are logged, if they are then, we - * know that we can safely clear the events in NVRAM. - * Next we'll sit and wait for something else to log. - */ -static ssize_t rtas_log_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) -{ - int error; - char *tmp; - unsigned long s; - unsigned long offset; - - if (!buf || count < rtas_error_log_buffer_max) - return -EINVAL; - - count = rtas_error_log_buffer_max; - - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - - tmp = kmalloc(count, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - - spin_lock_irqsave(&rtasd_log_lock, s); - /* if it's 0, then we know we got the last one (the one in NVRAM) */ - if (rtas_log_size == 0 && !no_logging) - nvram_clear_error_log(); - spin_unlock_irqrestore(&rtasd_log_lock, s); - - - error = wait_event_interruptible(rtas_log_wait, rtas_log_size); - if (error) - goto out; - - spin_lock_irqsave(&rtasd_log_lock, s); - offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK); - memcpy(tmp, &rtas_log_buf[offset], count); - - rtas_log_start += 1; - rtas_log_size -= 1; - spin_unlock_irqrestore(&rtasd_log_lock, s); - - error = copy_to_user(buf, tmp, count) ? -EFAULT : count; -out: - kfree(tmp); - return error; -} - -static unsigned int rtas_log_poll(struct file *file, poll_table * wait) -{ - poll_wait(file, &rtas_log_wait, wait); - if (rtas_log_size) - return POLLIN | POLLRDNORM; - return 0; -} - -struct file_operations proc_rtas_log_operations = { - .read = rtas_log_read, - .poll = rtas_log_poll, - .open = rtas_log_open, - .release = rtas_log_release, -}; - -static int enable_surveillance(int timeout) -{ - int error; - - error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout); - - if (error == 0) - return 0; - - if (error == -EINVAL) { - printk(KERN_INFO "rtasd: surveillance not supported\n"); - return 0; - } - - printk(KERN_ERR "rtasd: could not update surveillance\n"); - return -1; -} - -static int get_eventscan_parms(void) -{ - struct device_node *node; - int *ip; - - node = of_find_node_by_path("/rtas"); - - ip = (int *)get_property(node, "rtas-event-scan-rate", NULL); - if (ip == NULL) { - printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); - of_node_put(node); - return -1; - } - rtas_event_scan_rate = *ip; - DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate); - - /* Make room for the sequence number */ - rtas_error_log_max = rtas_get_error_log_max(); - rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); - - of_node_put(node); - - return 0; -} - -static void do_event_scan(int event_scan) -{ - int error; - do { - memset(logdata, 0, rtas_error_log_max); - error = rtas_call(event_scan, 4, 1, NULL, - RTAS_EVENT_SCAN_ALL_EVENTS, 0, - __pa(logdata), rtas_error_log_max); - if (error == -1) { - printk(KERN_ERR "event-scan failed\n"); - break; - } - - if (error == 0) - pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); - - } while(error == 0); -} - -static void do_event_scan_all_cpus(long delay) -{ - int cpu; - - lock_cpu_hotplug(); - cpu = first_cpu(cpu_online_map); - for (;;) { - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - do_event_scan(rtas_token("event-scan")); - set_cpus_allowed(current, CPU_MASK_ALL); - - /* Drop hotplug lock, and sleep for the specified delay */ - unlock_cpu_hotplug(); - msleep_interruptible(delay); - lock_cpu_hotplug(); - - cpu = next_cpu(cpu, cpu_online_map); - if (cpu == NR_CPUS) - break; - } - unlock_cpu_hotplug(); -} - -static int rtasd(void *unused) -{ - unsigned int err_type; - int event_scan = rtas_token("event-scan"); - int rc; - - daemonize("rtasd"); - - if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1) - goto error; - - rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER); - if (!rtas_log_buf) { - printk(KERN_ERR "rtasd: no memory\n"); - goto error; - } - - printk(KERN_INFO "RTAS daemon started\n"); - - DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); - - /* See if we have any error stored in NVRAM */ - memset(logdata, 0, rtas_error_log_max); - - rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type); - - /* We can use rtas_log_buf now */ - no_logging = 0; - - if (!rc) { - if (err_type != ERR_FLAG_ALREADY_LOGGED) { - pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); - } - } - - /* First pass. */ - do_event_scan_all_cpus(1000); - - if (surveillance_timeout != -1) { - DEBUG("enabling surveillance\n"); - enable_surveillance(surveillance_timeout); - DEBUG("surveillance enabled\n"); - } - - /* Delay should be at least one second since some - * machines have problems if we call event-scan too - * quickly. */ - for (;;) - do_event_scan_all_cpus(30000/rtas_event_scan_rate); - -error: - /* Should delete proc entries */ - return -EINVAL; -} - -static int __init rtas_init(void) -{ - struct proc_dir_entry *entry; - - /* No RTAS, only warn if we are on a pSeries box */ - if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { - if (systemcfg->platform & PLATFORM_PSERIES) - printk(KERN_INFO "rtasd: no event-scan on system\n"); - return 1; - } - - entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &proc_rtas_log_operations; - else - printk(KERN_ERR "Failed to create error_log proc entry\n"); - - if (kernel_thread(rtasd, NULL, CLONE_FS) < 0) - printk(KERN_ERR "Failed to start RTAS daemon\n"); - - return 0; -} - -static int __init surveillance_setup(char *str) -{ - int i; - - if (get_option(&str,&i)) { - if (i >= 0 && i <= 255) - surveillance_timeout = i; - } - - return 1; -} - -static int __init rtasmsgs_setup(char *str) -{ - if (strcmp(str, "on") == 0) - full_rtas_msgs = 1; - else if (strcmp(str, "off") == 0) - full_rtas_msgs = 0; - - return 1; -} -__initcall(rtas_init); -__setup("surveillance=", surveillance_setup); -__setup("rtasmsgs=", rtasmsgs_setup); diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index d9fd7866927f..d1bb611ea626 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -149,31 +149,11 @@ struct rtas_error_log { unsigned char buffer[1]; }; -struct flash_block { - char *data; - unsigned long length; -}; - -/* This struct is very similar but not identical to - * that needed by the rtas flash update. - * All we need to do for rtas is rewrite num_blocks - * into a version/length and translate the pointers - * to absolute. +/* + * This can be set by the rtas_flash module so that it can get called + * as the absolutely last thing before the kernel terminates. */ -#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) -struct flash_block_list { - unsigned long num_blocks; - struct flash_block_list *next; - struct flash_block blocks[FLASH_BLOCKS_PER_NODE]; -}; -struct flash_block_list_header { /* just the header of flash_block_list */ - unsigned long num_blocks; - struct flash_block_list *next; -}; -extern struct flash_block_list_header rtas_firmware_flash_list; -void rtas_fw_restart(char *cmd); -void rtas_fw_power_off(void); -void rtas_fw_halt(void); +extern void (*rtas_flash_term_hook)(int); extern struct rtas_t rtas; -- cgit v1.2.3 From 5f94548982ad8cb9867297e9e18e50ec7b8accea Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Nov 2005 22:51:46 -0500 Subject: Input: do not register statically allocated devices Do not register statically allocated input devices to prevent OOPS when attaching input interfaces since it requires class device to be properly initialized. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 26 +++++++++++++++----------- include/linux/input.h | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/input/input.c b/drivers/input/input.c index 1a1654caedd5..d543c0ce5229 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -377,7 +377,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int list_for_each_entry(dev, &input_dev_list, node) { - path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL; + path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); @@ -741,15 +741,21 @@ static void input_register_classdevice(struct input_dev *dev) sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group); } -void input_register_device(struct input_dev *dev) +int input_register_device(struct input_dev *dev) { struct input_handle *handle; struct input_handler *handler; struct input_device_id *id; - set_bit(EV_SYN, dev->evbit); + if (!dev->dynalloc) { + printk(KERN_WARNING "input: device %s is statically allocated, will not register\n" + "Please convert to input_allocate_device() or contact dtor_core@ameritech.net\n", + dev->name ? dev->name : ""); + return -EINVAL; + } init_MUTEX(&dev->sem); + set_bit(EV_SYN, dev->evbit); /* * If delay and period are pre-set by the driver, then autorepeating @@ -767,8 +773,7 @@ void input_register_device(struct input_dev *dev) INIT_LIST_HEAD(&dev->h_list); list_add_tail(&dev->node, &input_dev_list); - if (dev->dynalloc) - input_register_classdevice(dev); + input_register_classdevice(dev); list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) @@ -776,8 +781,9 @@ void input_register_device(struct input_dev *dev) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); - input_wakeup_procfs_readers(); + + return 0; } void input_unregister_device(struct input_dev *dev) @@ -797,11 +803,9 @@ void input_unregister_device(struct input_dev *dev) list_del_init(&dev->node); - if (dev->dynalloc) { - sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); - sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); - class_device_unregister(&dev->cdev); - } + sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); + sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); + class_device_unregister(&dev->cdev); input_wakeup_procfs_readers(); } diff --git a/include/linux/input.h b/include/linux/input.h index f623c745c21c..3c5823368ddb 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1007,7 +1007,7 @@ static inline void input_put_device(struct input_dev *dev) class_device_put(&dev->cdev); } -void input_register_device(struct input_dev *); +int input_register_device(struct input_dev *); void input_unregister_device(struct input_dev *); void input_register_handler(struct input_handler *); -- cgit v1.2.3 From cab0af98dfbbf8076d1af01f2927af491a76a33f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 Nov 2005 15:30:49 +1100 Subject: powerpc: Make set_dabr() a ppc_md function Move pSeries specific code in set_dabr() into a ppc_md function, this will allow us to keep plpar_wrappers.h private to platforms/pseries. Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/process.c | 22 +++++----------------- arch/powerpc/platforms/pseries/setup.c | 12 ++++++++++++ include/asm-powerpc/machdep.h | 1 + 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 8f85dabe4df3..96843211cc5c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -48,8 +48,8 @@ #include #ifdef CONFIG_PPC64 #include -#include #include +#include #endif extern unsigned long _get_SP(void); @@ -201,27 +201,15 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) } #endif /* CONFIG_SPE */ -static void set_dabr_spr(unsigned long val) -{ - mtspr(SPRN_DABR, val); -} - int set_dabr(unsigned long dabr) { - int ret = 0; - #ifdef CONFIG_PPC64 - if (firmware_has_feature(FW_FEATURE_XDABR)) { - /* We want to catch accesses from kernel and userspace */ - unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER; - ret = plpar_set_xdabr(dabr, flags); - } else if (firmware_has_feature(FW_FEATURE_DABR)) { - ret = plpar_set_dabr(dabr); - } else + if (ppc_md.set_dabr) + return ppc_md.set_dabr(dabr); #endif - set_dabr_spr(dabr); - return ret; + mtspr(SPRN_DABR, dabr); + return 0; } #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index c0a3d918148a..ee468f07f378 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -350,6 +350,16 @@ static void pSeries_mach_cpu_die(void) for(;;); } +static int pseries_set_dabr(unsigned long dabr) +{ + if (firmware_has_feature(FW_FEATURE_XDABR)) { + /* We want to catch accesses from kernel and userspace */ + return plpar_set_xdabr(dabr, H_DABRX_KERNEL | H_DABRX_USER); + } + + return plpar_set_dabr(dabr); +} + /* * Early initialization. Relocation is on but do not reference unbolted pages @@ -385,6 +395,8 @@ static void __init pSeries_init_early(void) DBG("Hello World !\n"); } + if (firmware_has_feature(FW_FEATURE_XDABR | FW_FEATURE_DABR)) + ppc_md.set_dabr = pseries_set_dabr; iommu_init_early_pSeries(); diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 451b345cfc78..629ca964b974 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -80,6 +80,7 @@ struct machdep_calls { void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); void (*irq_bus_setup)(struct pci_bus *bus); + int (*set_dabr)(unsigned long dabr); #endif int (*probe)(int platform); -- cgit v1.2.3 From a1218720321d778134914cf90ef54cf0d1d8477c Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 Nov 2005 15:33:31 +1100 Subject: powerpc: Move plpar_wrappers.h into arch/powerpc/platforms/pseries Move plpar_wrappers.h into arch/powerpc/platforms/pseries, fixup white space, and update callers. Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/iommu.c | 3 +- arch/powerpc/platforms/pseries/lpar.c | 3 +- arch/powerpc/platforms/pseries/plpar_wrappers.h | 107 +++++++++++++++++++++ arch/powerpc/platforms/pseries/setup.c | 3 +- arch/powerpc/platforms/pseries/smp.c | 3 +- include/asm-ppc64/plpar_wrappers.h | 120 ------------------------ 6 files changed, 115 insertions(+), 124 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/plpar_wrappers.h delete mode 100644 include/asm-ppc64/plpar_wrappers.h (limited to 'include') diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 9e90d41131d8..9e58a1922109 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -42,13 +42,14 @@ #include #include #include -#include #include #include #include #include #include +#include "plpar_wrappers.h" + #define DBG(fmt...) extern int is_python(struct device_node *); diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 268d8362dde7..8a7bda3db677 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -38,7 +38,8 @@ #include #include #include -#include + +#include "plpar_wrappers.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h new file mode 100644 index 000000000000..2457be2e217e --- /dev/null +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -0,0 +1,107 @@ +#ifndef _PSERIES_PLPAR_WRAPPERS_H +#define _PSERIES_PLPAR_WRAPPERS_H + +#include + +static inline long poll_pending(void) +{ + unsigned long dummy; + return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, &dummy, &dummy, &dummy); +} + +static inline long prod_processor(void) +{ + plpar_hcall_norets(H_PROD); + return 0; +} + +static inline long cede_processor(void) +{ + plpar_hcall_norets(H_CEDE); + return 0; +} + +static inline long register_vpa(unsigned long flags, unsigned long proc, + unsigned long vpa) +{ + return plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); +} + +void vpa_init(int cpu); + +static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex, + unsigned long avpn, unsigned long *old_pteh_ret, + unsigned long *old_ptel_ret) +{ + unsigned long dummy; + return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, old_pteh_ret, + old_ptel_ret, &dummy); +} + +static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, + unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) +{ + unsigned long dummy; + return plpar_hcall(H_READ, flags, ptex, 0, 0, old_pteh_ret, + old_ptel_ret, &dummy); +} + +static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, + unsigned long avpn) +{ + return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn); +} + +static inline long plpar_tce_get(unsigned long liobn, unsigned long ioba, + unsigned long *tce_ret) +{ + unsigned long dummy; + return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, tce_ret, &dummy, + &dummy); +} + +static inline long plpar_tce_put(unsigned long liobn, unsigned long ioba, + unsigned long tceval) +{ + return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval); +} + +static inline long plpar_tce_put_indirect(unsigned long liobn, + unsigned long ioba, unsigned long page, unsigned long count) +{ + return plpar_hcall_norets(H_PUT_TCE_INDIRECT, liobn, ioba, page, count); +} + +static inline long plpar_tce_stuff(unsigned long liobn, unsigned long ioba, + unsigned long tceval, unsigned long count) +{ + return plpar_hcall_norets(H_STUFF_TCE, liobn, ioba, tceval, count); +} + +static inline long plpar_get_term_char(unsigned long termno, + unsigned long *len_ret, char *buf_ret) +{ + unsigned long *lbuf = (unsigned long *)buf_ret; /* TODO: alignment? */ + return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, len_ret, + lbuf + 0, lbuf + 1); +} + +static inline long plpar_put_term_char(unsigned long termno, unsigned long len, + const char *buffer) +{ + unsigned long *lbuf = (unsigned long *)buffer; /* TODO: alignment? */ + return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0], + lbuf[1]); +} + +static inline long plpar_set_xdabr(unsigned long address, unsigned long flags) +{ + return plpar_hcall_norets(H_SET_XDABR, address, flags); +} + +static inline long plpar_set_dabr(unsigned long val) +{ + return plpar_hcall_norets(H_SET_DABR, val); +} + +#endif /* _PSERIES_PLPAR_WRAPPERS_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ee468f07f378..d54e1e4c7c63 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -58,7 +58,6 @@ #include #include #include -#include #include "xics.h" #include #include @@ -67,6 +66,8 @@ #include #include +#include "plpar_wrappers.h" + #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) #else diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 9c9458ddfc25..7a243e8ccd7e 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -44,10 +44,11 @@ #include #include #include -#include #include #include +#include "plpar_wrappers.h" + #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) #else diff --git a/include/asm-ppc64/plpar_wrappers.h b/include/asm-ppc64/plpar_wrappers.h deleted file mode 100644 index 72dd2449ee76..000000000000 --- a/include/asm-ppc64/plpar_wrappers.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef _PPC64_PLPAR_WRAPPERS_H -#define _PPC64_PLPAR_WRAPPERS_H - -#include - -static inline long poll_pending(void) -{ - unsigned long dummy; - return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, - &dummy, &dummy, &dummy); -} - -static inline long prod_processor(void) -{ - plpar_hcall_norets(H_PROD); - return(0); -} - -static inline long cede_processor(void) -{ - plpar_hcall_norets(H_CEDE); - return(0); -} - -static inline long register_vpa(unsigned long flags, unsigned long proc, - unsigned long vpa) -{ - return plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); -} - -void vpa_init(int cpu); - -static inline long plpar_pte_remove(unsigned long flags, - unsigned long ptex, - unsigned long avpn, - unsigned long *old_pteh_ret, - unsigned long *old_ptel_ret) -{ - unsigned long dummy; - return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, - old_pteh_ret, old_ptel_ret, &dummy); -} - -static inline long plpar_pte_read(unsigned long flags, - unsigned long ptex, - unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) -{ - unsigned long dummy; - return plpar_hcall(H_READ, flags, ptex, 0, 0, - old_pteh_ret, old_ptel_ret, &dummy); -} - -static inline long plpar_pte_protect(unsigned long flags, - unsigned long ptex, - unsigned long avpn) -{ - return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn); -} - -static inline long plpar_tce_get(unsigned long liobn, - unsigned long ioba, - unsigned long *tce_ret) -{ - unsigned long dummy; - return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, - tce_ret, &dummy, &dummy); -} - -static inline long plpar_tce_put(unsigned long liobn, - unsigned long ioba, - unsigned long tceval) -{ - return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval); -} - -static inline long plpar_tce_put_indirect(unsigned long liobn, - unsigned long ioba, - unsigned long page, - unsigned long count) -{ - return plpar_hcall_norets(H_PUT_TCE_INDIRECT, liobn, ioba, page, count); -} - -static inline long plpar_tce_stuff(unsigned long liobn, - unsigned long ioba, - unsigned long tceval, - unsigned long count) -{ - return plpar_hcall_norets(H_STUFF_TCE, liobn, ioba, tceval, count); -} - -static inline long plpar_get_term_char(unsigned long termno, - unsigned long *len_ret, - char *buf_ret) -{ - unsigned long *lbuf = (unsigned long *)buf_ret; /* ToDo: alignment? */ - return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, - len_ret, lbuf+0, lbuf+1); -} - -static inline long plpar_put_term_char(unsigned long termno, - unsigned long len, - const char *buffer) -{ - unsigned long *lbuf = (unsigned long *)buffer; /* ToDo: alignment? */ - return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0], - lbuf[1]); -} - -static inline long plpar_set_xdabr(unsigned long address, unsigned long flags) -{ - return plpar_hcall_norets(H_SET_XDABR, address, flags); -} - -static inline long plpar_set_dabr(unsigned long val) -{ - return plpar_hcall_norets(H_SET_DABR, val); -} - -#endif /* _PPC64_PLPAR_WRAPPERS_H */ -- cgit v1.2.3 From e1df870d546f4d033030615aa3d01c0341c1ef1f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 Nov 2005 15:35:45 +1100 Subject: powerpc: Merge asm-ppc/kexec.h and asm-ppc64/kexec.h Merge include/asm-ppc/kexec.h and include/asm-ppc64/kexec.h. The only thing that's really changed is that we now allocate crash_notes properly on PPC32. It's address is exported via sysfs, so it's not correct for it to be a pointer. I've also removed some of the "we don't use this" comments, because they're wrong (or perhaps were referring only to arch code). Signed-off-by: Michael Ellerman --- arch/ppc/kernel/machine_kexec.c | 2 +- include/asm-powerpc/kexec.h | 49 +++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/kexec.h | 40 --------------------------------- include/asm-ppc64/kexec.h | 41 ---------------------------------- 4 files changed, 50 insertions(+), 82 deletions(-) create mode 100644 include/asm-powerpc/kexec.h delete mode 100644 include/asm-ppc/kexec.h delete mode 100644 include/asm-ppc64/kexec.h (limited to 'include') diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c index a72787747df7..a882b0dbe8de 100644 --- a/arch/ppc/kernel/machine_kexec.c +++ b/arch/ppc/kernel/machine_kexec.c @@ -32,7 +32,7 @@ const extern unsigned int relocate_new_kernel_size; * Provide a dummy crash_notes definition while crash dump arrives to ppc. * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. */ -void *crash_notes = NULL; +note_buf_t crash_notes[NR_CPUS]; void machine_shutdown(void) { diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h new file mode 100644 index 000000000000..062ab9ba68eb --- /dev/null +++ b/include/asm-powerpc/kexec.h @@ -0,0 +1,49 @@ +#ifndef _ASM_POWERPC_KEXEC_H +#define _ASM_POWERPC_KEXEC_H + +/* + * Maximum page that is mapped directly into kernel memory. + * XXX: Since we copy virt we can use any page we allocate + */ +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) + +/* + * Maximum address we can reach in physical address mode. + * XXX: I want to allow initrd in highmem. Otherwise set to rmo on LPAR. + */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) + +/* Maximum address we can use for the control code buffer */ +#ifdef __powerpc64__ +#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL) +#else +/* TASK_SIZE, probably left over from use_mm ?? */ +#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE +#endif + +#define KEXEC_CONTROL_CODE_SIZE 4096 + +/* The native architecture */ +#ifdef __powerpc64__ +#define KEXEC_ARCH KEXEC_ARCH_PPC64 +#else +#define KEXEC_ARCH KEXEC_ARCH_PPC +#endif + +#ifndef __ASSEMBLY__ + +#define MAX_NOTE_BYTES 1024 +typedef u32 note_buf_t[MAX_NOTE_BYTES / sizeof(u32)]; + +extern note_buf_t crash_notes[]; + +#ifdef __powerpc64__ +extern void kexec_smp_wait(void); /* get and clear naca physid, wait for + master to copy new code to 0 */ +#else +struct kimage; +extern void machine_kexec_simple(struct kimage *image); +#endif + +#endif /* ! __ASSEMBLY__ */ +#endif /* _ASM_POWERPC_KEXEC_H */ diff --git a/include/asm-ppc/kexec.h b/include/asm-ppc/kexec.h deleted file mode 100644 index 6d2aa0aa4642..000000000000 --- a/include/asm-ppc/kexec.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _PPC_KEXEC_H -#define _PPC_KEXEC_H - -#ifdef CONFIG_KEXEC - -/* - * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. - * I.e. Maximum page that is mapped directly into kernel memory, - * and kmap is not required. - * - * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct - * calculation for the amount of memory directly mappable into the - * kernel memory space. - */ - -/* Maximum physical address we can use pages from */ -#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) -/* Maximum address we can reach in physical address mode */ -#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) -/* Maximum address we can use for the control code buffer */ -#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE - -#define KEXEC_CONTROL_CODE_SIZE 4096 - -/* The native architecture */ -#define KEXEC_ARCH KEXEC_ARCH_PPC - -#ifndef __ASSEMBLY__ - -extern void *crash_notes; - -struct kimage; - -extern void machine_kexec_simple(struct kimage *image); - -#endif /* __ASSEMBLY__ */ - -#endif /* CONFIG_KEXEC */ - -#endif /* _PPC_KEXEC_H */ diff --git a/include/asm-ppc64/kexec.h b/include/asm-ppc64/kexec.h deleted file mode 100644 index 511908afaeeb..000000000000 --- a/include/asm-ppc64/kexec.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _PPC64_KEXEC_H -#define _PPC64_KEXEC_H - -/* - * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. - * I.e. Maximum page that is mapped directly into kernel memory, - * and kmap is not required. - */ - -/* Maximum physical address we can use pages from */ -/* XXX: since we copy virt we can use any page we allocate */ -#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) - -/* Maximum address we can reach in physical address mode */ -/* XXX: I want to allow initrd in highmem. otherwise set to rmo on lpar */ -#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) - -/* Maximum address we can use for the control code buffer */ -/* XXX: unused today, ppc32 uses TASK_SIZE, probably left over from use_mm */ -#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL) - -/* XXX: today we don't use this at all, althogh we have a static stack */ -#define KEXEC_CONTROL_CODE_SIZE 4096 - -/* The native architecture */ -#define KEXEC_ARCH KEXEC_ARCH_PPC64 - -#define MAX_NOTE_BYTES 1024 - -#ifndef __ASSEMBLY__ - -typedef u32 note_buf_t[MAX_NOTE_BYTES/4]; - -extern note_buf_t crash_notes[]; - -extern void kexec_smp_wait(void); /* get and clear naca physid, wait for - master to copy new code to 0 */ - -#endif /* __ASSEMBLY__ */ -#endif /* _PPC_KEXEC_H */ - -- cgit v1.2.3 From c5a1ebd24547df5738138ebc154e1abccfa85468 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 Nov 2005 16:02:23 +1100 Subject: powerpc: merge stat.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/stat.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/stat.h | 69 --------------------------------------- include/asm-ppc64/stat.h | 60 ---------------------------------- 3 files changed, 81 insertions(+), 129 deletions(-) create mode 100644 include/asm-powerpc/stat.h delete mode 100644 include/asm-ppc/stat.h delete mode 100644 include/asm-ppc64/stat.h (limited to 'include') diff --git a/include/asm-powerpc/stat.h b/include/asm-powerpc/stat.h new file mode 100644 index 000000000000..e4edc510b530 --- /dev/null +++ b/include/asm-powerpc/stat.h @@ -0,0 +1,81 @@ +#ifndef _ASM_POWERPC_STAT_H +#define _ASM_POWERPC_STAT_H +/* + * 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 + +#define STAT_HAVE_NSEC 1 + +#ifndef __powerpc64__ +struct __old_kernel_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; +}; +#endif /* !__powerpc64__ */ + +struct stat { + unsigned long st_dev; + ino_t st_ino; +#ifdef __powerpc64__ + nlink_t st_nlink; + mode_t st_mode; +#else + mode_t st_mode; + nlink_t st_nlink; +#endif + uid_t st_uid; + gid_t st_gid; + unsigned long st_rdev; + off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; +#ifdef __powerpc64__ + unsigned long __unused6; +#endif +}; + +/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */ +struct stat64 { + unsigned long long st_dev; /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + unsigned short __pad2; + long long st_size; /* Size of file, in bytes. */ + int st_blksize; /* Optimal block size for I/O. */ + long long st_blocks; /* Number 512-byte blocks allocated. */ + int st_atime; /* Time of last access. */ + unsigned int st_atime_nsec; + int st_mtime; /* Time of last modification. */ + unsigned int st_mtime_nsec; + int st_ctime; /* Time of last status change. */ + unsigned int st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif /* _ASM_POWERPC_STAT_H */ diff --git a/include/asm-ppc/stat.h b/include/asm-ppc/stat.h deleted file mode 100644 index cadb34298496..000000000000 --- a/include/asm-ppc/stat.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _PPC_STAT_H -#define _PPC_STAT_H - -#ifdef __KERNEL__ -#include -#endif /* __KERNEL__ */ - -struct __old_kernel_stat { - unsigned short st_dev; - unsigned short st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned long st_size; - unsigned long st_atime; - unsigned long st_mtime; - unsigned long st_ctime; -}; - -#define STAT_HAVE_NSEC 1 - -struct stat { - unsigned st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - unsigned st_rdev; - off_t st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long __unused4; - unsigned long __unused5; -}; - -/* This matches struct stat64 in glibc2.1. - */ -struct stat64 { - unsigned long long st_dev; /* Device. */ - unsigned long long st_ino; /* File serial number. */ - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group. */ - unsigned long long st_rdev; /* Device number, if device. */ - unsigned short int __pad2; - long long st_size; /* Size of file, in bytes. */ - long st_blksize; /* Optimal block size for I/O. */ - - long long st_blocks; /* Number 512-byte blocks allocated. */ - long st_atime; /* Time of last access. */ - unsigned long st_atime_nsec; - long st_mtime; /* Time of last modification. */ - unsigned long int st_mtime_nsec; - long st_ctime; /* Time of last status change. */ - unsigned long int st_ctime_nsec; - unsigned long int __unused4; - unsigned long int __unused5; -}; -#endif diff --git a/include/asm-ppc64/stat.h b/include/asm-ppc64/stat.h deleted file mode 100644 index 973a5f97951d..000000000000 --- a/include/asm-ppc64/stat.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _PPC64_STAT_H -#define _PPC64_STAT_H - -/* - * 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 - -struct stat { - unsigned long st_dev; - ino_t st_ino; - nlink_t st_nlink; - mode_t st_mode; - uid_t st_uid; - gid_t st_gid; - unsigned long st_rdev; - off_t st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long __unused4; - unsigned long __unused5; - unsigned long __unused6; -}; - -#define STAT_HAVE_NSEC 1 - -/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */ -struct stat64 { - unsigned long st_dev; /* Device. */ - unsigned long st_ino; /* File serial number. */ - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group. */ - unsigned long st_rdev; /* Device number, if device. */ - unsigned short __pad2; - long st_size; /* Size of file, in bytes. */ - int st_blksize; /* Optimal block size for I/O. */ - - long st_blocks; /* Number 512-byte blocks allocated. */ - int st_atime; /* Time of last access. */ - int st_atime_nsec; - int st_mtime; /* Time of last modification. */ - int st_mtime_nsec; - int st_ctime; /* Time of last status change. */ - int st_ctime_nsec; - unsigned int __unused4; - unsigned int __unused5; -}; -#endif -- cgit v1.2.3 From da80d460bf4606671df3ba53408f45ab848e67ba Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 Nov 2005 15:14:36 +1100 Subject: powerpc: merge ptrace.h Move struct ptregs32 into asm-ppc64/ppc32.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/ptrace.h | 248 +++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/ptrace.h | 152 -------------------------- include/asm-ppc64/ppc32.h | 16 +++ include/asm-ppc64/ptrace.h | 213 ------------------------------------- 4 files changed, 264 insertions(+), 365 deletions(-) create mode 100644 include/asm-powerpc/ptrace.h delete mode 100644 include/asm-ppc/ptrace.h delete mode 100644 include/asm-ppc64/ptrace.h (limited to 'include') diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h new file mode 100644 index 000000000000..1f7ecdb0b6ce --- /dev/null +++ b/include/asm-powerpc/ptrace.h @@ -0,0 +1,248 @@ +#ifndef _ASM_POWERPC_PTRACE_H +#define _ASM_POWERPC_PTRACE_H + +/* + * Copyright (C) 2001 PPC64 Team, IBM Corp + * + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry. + * + * this should only contain volatile regs + * since we can keep non-volatile in the thread_struct + * should set this up when only volatiles are saved + * by intr code. + * + * Since this is going on the stack, *CARE MUST BE TAKEN* to insure + * that the overall structure is a multiple of 16 bytes in length. + * + * Note that the offsets of the fields in this struct correspond with + * the PT_* values below. This simplifies arch/powerpc/kernel/ptrace.c. + * + * 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. + */ + +#ifndef __ASSEMBLY__ + +struct pt_regs { + unsigned long gpr[32]; + unsigned long nip; + unsigned long msr; + unsigned long orig_gpr3; /* Used for restarting system calls */ + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; +#ifdef __powerpc64__ + unsigned long softe; /* Soft enabled/disabled */ +#else + unsigned long mq; /* 601 only (not used at present) */ + /* Used on APUS to hold IPL value. */ +#endif + unsigned long trap; /* Reason for being here */ + /* N.B. for critical exceptions on 4xx, the dar and dsisr + fields are overloaded to hold srr0 and srr1. */ + unsigned long dar; /* Fault registers */ + unsigned long dsisr; /* on 4xx/Book-E used for ESR */ + unsigned long result; /* Result of a system call */ +}; + +#endif /* __ASSEMBLY__ */ + +#ifdef __KERNEL__ + +#ifdef __powerpc64__ + +#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ + +/* Size of dummy stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 128 +#define __SIGNAL_FRAMESIZE32 64 + +#else /* __powerpc64__ */ + +#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */ + +/* Size of stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 64 + +#endif /* __powerpc64__ */ + +#ifndef __ASSEMBLY__ + +#define instruction_pointer(regs) ((regs)->nip) +#ifdef CONFIG_SMP +extern unsigned long profile_pc(struct pt_regs *regs); +#else +#define profile_pc(regs) instruction_pointer(regs) +#endif + +#ifdef __powerpc64__ +#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) +#else +#define user_mode(regs) (((regs)->msr & MSR_PR) != 0) +#endif + +#define force_successful_syscall_return() \ + do { \ + current_thread_info()->syscall_noerror = 1; \ + } while(0) + +/* + * We use the least-significant bit of the trap field to indicate + * whether we have saved the full set of registers, or only a + * partial set. A 1 there means the partial set. + * On 4xx we use the next bit to indicate whether the exception + * is a critical exception (1 means it is). + */ +#define FULL_REGS(regs) (((regs)->trap & 1) == 0) +#ifndef __powerpc64__ +#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) == 0) +#endif /* ! __powerpc64__ */ +#define TRAP(regs) ((regs)->trap & ~0xF) +#ifdef __powerpc64__ +#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1) +#else +#define CHECK_FULL_REGS(regs) \ +do { \ + if ((regs)->trap & 1) \ + printk(KERN_CRIT "%s: partial register set\n", __FUNCTION__); \ +} while (0) +#endif /* __powerpc64__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +/* + * Offsets used by 'ptrace' system call interface. + * These can't be changed without breaking binary compatibility + * with MkLinux, etc. + */ +#define PT_R0 0 +#define PT_R1 1 +#define PT_R2 2 +#define PT_R3 3 +#define PT_R4 4 +#define PT_R5 5 +#define PT_R6 6 +#define PT_R7 7 +#define PT_R8 8 +#define PT_R9 9 +#define PT_R10 10 +#define PT_R11 11 +#define PT_R12 12 +#define PT_R13 13 +#define PT_R14 14 +#define PT_R15 15 +#define PT_R16 16 +#define PT_R17 17 +#define PT_R18 18 +#define PT_R19 19 +#define PT_R20 20 +#define PT_R21 21 +#define PT_R22 22 +#define PT_R23 23 +#define PT_R24 24 +#define PT_R25 25 +#define PT_R26 26 +#define PT_R27 27 +#define PT_R28 28 +#define PT_R29 29 +#define PT_R30 30 +#define PT_R31 31 + +#define PT_NIP 32 +#define PT_MSR 33 +#ifdef __KERNEL__ +#define PT_ORIG_R3 34 +#endif +#define PT_CTR 35 +#define PT_LNK 36 +#define PT_XER 37 +#define PT_CCR 38 +#ifndef __powerpc64__ +#define PT_MQ 39 +#else +#define PT_SOFTE 39 +#define PT_TRAP 40 +#define PT_DAR 41 +#define PT_DSISR 42 +#define PT_RESULT 43 +#endif + +#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ + +#ifndef __powerpc64__ + +#define PT_FPR31 (PT_FPR0 + 2*31) +#define PT_FPSCR (PT_FPR0 + 2*32 + 1) + +#else /* __powerpc64__ */ + +#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */ + +#ifdef __KERNEL__ +#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */ +#endif + +#define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */ +#define PT_VSCR (PT_VR0 + 32*2 + 1) +#define PT_VRSAVE (PT_VR0 + 33*2) + +#ifdef __KERNEL__ +#define PT_VR0_32 164 /* each Vector reg occupies 4 slots in 32-bit */ +#define PT_VSCR_32 (PT_VR0 + 32*4 + 3) +#define PT_VRSAVE_32 (PT_VR0 + 33*4) +#endif + +#endif /* __powerpc64__ */ + +/* + * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. + * The transfer totals 34 quadword. Quadwords 0-31 contain the + * corresponding vector registers. Quadword 32 contains the vscr as the + * last word (offset 12) within that quadword. Quadword 33 contains the + * vrsave as the first word (offset 0) within the quadword. + * + * This definition of the VMX state is compatible with the current PPC32 + * ptrace interface. This allows signal handling and ptrace to use the same + * structures. This also simplifies the implementation of a bi-arch + * (combined (32- and 64-bit) gdb. + */ +#define PTRACE_GETVRREGS 18 +#define PTRACE_SETVRREGS 19 + +#ifndef __powerpc64__ +/* Get/set all the upper 32-bits of the SPE registers, accumulator, and + * spefscr, in one go */ +#define PTRACE_GETEVRREGS 20 +#define PTRACE_SETEVRREGS 21 +#endif /* __powerpc64__ */ + +/* + * Get or set a debug register. The first 16 are DABR registers and the + * second 16 are IABR registers. + */ +#define PTRACE_GET_DEBUGREG 25 +#define PTRACE_SET_DEBUGREG 26 + +#ifdef __powerpc64__ +/* Additional PTRACE requests implemented on PowerPC. */ +#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ +#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ +#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ +#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ + +/* Calls to trace a 64bit program from a 32bit program */ +#define PPC_PTRACE_PEEKTEXT_3264 0x95 +#define PPC_PTRACE_PEEKDATA_3264 0x94 +#define PPC_PTRACE_POKETEXT_3264 0x93 +#define PPC_PTRACE_POKEDATA_3264 0x92 +#define PPC_PTRACE_PEEKUSR_3264 0x91 +#define PPC_PTRACE_POKEUSR_3264 0x90 +#endif /* __powerpc64__ */ + +#endif /* _ASM_POWERPC_PTRACE_H */ diff --git a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h deleted file mode 100644 index c34fb4e37a97..000000000000 --- a/include/asm-ppc/ptrace.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef _PPC_PTRACE_H -#define _PPC_PTRACE_H - -/* - * This struct defines the way the registers are stored on the - * kernel stack during a system call or other kernel entry. - * - * this should only contain volatile regs - * since we can keep non-volatile in the thread_struct - * should set this up when only volatiles are saved - * by intr code. - * - * Since this is going on the stack, *CARE MUST BE TAKEN* to insure - * that the overall structure is a multiple of 16 bytes in length. - * - * Note that the offsets of the fields in this struct correspond with - * the PT_* values below. This simplifies arch/ppc/kernel/ptrace.c. - */ - -#ifndef __ASSEMBLY__ -struct pt_regs { - unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long orig_gpr3; /* Used for restarting system calls */ - unsigned long ctr; - unsigned long link; - unsigned long xer; - unsigned long ccr; - unsigned long mq; /* 601 only (not used at present) */ - /* Used on APUS to hold IPL value. */ - unsigned long trap; /* Reason for being here */ - /* N.B. for critical exceptions on 4xx, the dar and dsisr - fields are overloaded to hold srr0 and srr1. */ - unsigned long dar; /* Fault registers */ - unsigned long dsisr; /* on 4xx/Book-E used for ESR */ - unsigned long result; /* Result of a system call */ -}; - -#endif /* __ASSEMBLY__ */ - -#ifdef __KERNEL__ -#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */ - -/* Size of stack frame allocated when calling signal handler. */ -#define __SIGNAL_FRAMESIZE 64 - -#ifndef __ASSEMBLY__ -#define instruction_pointer(regs) ((regs)->nip) -#ifdef CONFIG_SMP -extern unsigned long profile_pc(struct pt_regs *regs); -#else -#define profile_pc(regs) instruction_pointer(regs) -#endif - -#define user_mode(regs) (((regs)->msr & MSR_PR) != 0) - -#define force_successful_syscall_return() \ - do { \ - current_thread_info()->syscall_noerror = 1; \ - } while(0) - -/* - * We use the least-significant bit of the trap field to indicate - * whether we have saved the full set of registers, or only a - * partial set. A 1 there means the partial set. - * On 4xx we use the next bit to indicate whether the exception - * is a critical exception (1 means it is). - */ -#define FULL_REGS(regs) (((regs)->trap & 1) == 0) -#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) == 0) -#define TRAP(regs) ((regs)->trap & ~0xF) - -#define CHECK_FULL_REGS(regs) \ -do { \ - if ((regs)->trap & 1) \ - printk(KERN_CRIT "%s: partial register set\n", __FUNCTION__); \ -} while (0) -#endif /* __ASSEMBLY__ */ - -#endif /* __KERNEL__ */ - -/* - * Offsets used by 'ptrace' system call interface. - * These can't be changed without breaking binary compatibility - * with MkLinux, etc. - */ -#define PT_R0 0 -#define PT_R1 1 -#define PT_R2 2 -#define PT_R3 3 -#define PT_R4 4 -#define PT_R5 5 -#define PT_R6 6 -#define PT_R7 7 -#define PT_R8 8 -#define PT_R9 9 -#define PT_R10 10 -#define PT_R11 11 -#define PT_R12 12 -#define PT_R13 13 -#define PT_R14 14 -#define PT_R15 15 -#define PT_R16 16 -#define PT_R17 17 -#define PT_R18 18 -#define PT_R19 19 -#define PT_R20 20 -#define PT_R21 21 -#define PT_R22 22 -#define PT_R23 23 -#define PT_R24 24 -#define PT_R25 25 -#define PT_R26 26 -#define PT_R27 27 -#define PT_R28 28 -#define PT_R29 29 -#define PT_R30 30 -#define PT_R31 31 - -#define PT_NIP 32 -#define PT_MSR 33 -#ifdef __KERNEL__ -#define PT_ORIG_R3 34 -#endif -#define PT_CTR 35 -#define PT_LNK 36 -#define PT_XER 37 -#define PT_CCR 38 -#define PT_MQ 39 - -#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ -#define PT_FPR31 (PT_FPR0 + 2*31) -#define PT_FPSCR (PT_FPR0 + 2*32 + 1) - -/* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go */ -#define PTRACE_GETVRREGS 18 -#define PTRACE_SETVRREGS 19 - -/* Get/set all the upper 32-bits of the SPE registers, accumulator, and - * spefscr, in one go */ -#define PTRACE_GETEVRREGS 20 -#define PTRACE_SETEVRREGS 21 - -/* - * Get or set a debug register. The first 16 are DABR registers and the - * second 16 are IABR registers. - */ -#define PTRACE_GET_DEBUGREG 25 -#define PTRACE_SET_DEBUGREG 26 - -#endif diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h index 3945a55d112a..90e562771791 100644 --- a/include/asm-ppc64/ppc32.h +++ b/include/asm-ppc64/ppc32.h @@ -91,6 +91,22 @@ typedef struct sigaltstack_32 { compat_size_t ss_size; } stack_32_t; +struct pt_regs32 { + unsigned int gpr[32]; + unsigned int nip; + unsigned int msr; + unsigned int orig_gpr3; /* Used for restarting system calls */ + unsigned int ctr; + unsigned int link; + unsigned int xer; + unsigned int ccr; + unsigned int mq; /* 601 only (not used at present) */ + unsigned int trap; /* Reason for being here */ + unsigned int dar; /* Fault registers */ + unsigned int dsisr; + unsigned int result; /* Result of a system call */ +}; + struct sigcontext32 { unsigned int _unused[4]; int signal; diff --git a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h deleted file mode 100644 index 3a55377f1fd3..000000000000 --- a/include/asm-ppc64/ptrace.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef _PPC64_PTRACE_H -#define _PPC64_PTRACE_H - -/* - * Copyright (C) 2001 PPC64 Team, IBM Corp - * - * This struct defines the way the registers are stored on the - * kernel stack during a system call or other kernel entry. - * - * this should only contain volatile regs - * since we can keep non-volatile in the thread_struct - * should set this up when only volatiles are saved - * by intr code. - * - * Since this is going on the stack, *CARE MUST BE TAKEN* to insure - * that the overall structure is a multiple of 16 bytes in length. - * - * Note that the offsets of the fields in this struct correspond with - * the PT_* values below. This simplifies arch/ppc64/kernel/ptrace.c. - * - * 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. - */ - -#ifndef __ASSEMBLY__ - -struct pt_regs { - unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long orig_gpr3; /* Used for restarting system calls */ - unsigned long ctr; - unsigned long link; - unsigned long xer; - unsigned long ccr; - unsigned long softe; /* Soft enabled/disabled */ - unsigned long trap; /* Reason for being here */ - unsigned long dar; /* Fault registers */ - unsigned long dsisr; - unsigned long result; /* Result of a system call */ -}; - -struct pt_regs32 { - unsigned int gpr[32]; - unsigned int nip; - unsigned int msr; - unsigned int orig_gpr3; /* Used for restarting system calls */ - unsigned int ctr; - unsigned int link; - unsigned int xer; - unsigned int ccr; - unsigned int mq; /* 601 only (not used at present) */ - unsigned int trap; /* Reason for being here */ - unsigned int dar; /* Fault registers */ - unsigned int dsisr; - unsigned int result; /* Result of a system call */ -}; - -#ifdef __KERNEL__ - -#define instruction_pointer(regs) ((regs)->nip) - -#ifdef CONFIG_SMP -extern unsigned long profile_pc(struct pt_regs *regs); -#else -#define profile_pc(regs) instruction_pointer(regs) -#endif - -#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) - -#define force_successful_syscall_return() \ - (current_thread_info()->syscall_noerror = 1) - -/* - * We use the least-significant bit of the trap field to indicate - * whether we have saved the full set of registers, or only a - * partial set. A 1 there means the partial set. - */ -#define FULL_REGS(regs) (((regs)->trap & 1) == 0) -#define TRAP(regs) ((regs)->trap & ~0xF) -#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1) - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ - -/* Size of dummy stack frame allocated when calling signal handler. */ -#define __SIGNAL_FRAMESIZE 128 -#define __SIGNAL_FRAMESIZE32 64 - -/* - * Offsets used by 'ptrace' system call interface. - */ -#define PT_R0 0 -#define PT_R1 1 -#define PT_R2 2 -#define PT_R3 3 -#define PT_R4 4 -#define PT_R5 5 -#define PT_R6 6 -#define PT_R7 7 -#define PT_R8 8 -#define PT_R9 9 -#define PT_R10 10 -#define PT_R11 11 -#define PT_R12 12 -#define PT_R13 13 -#define PT_R14 14 -#define PT_R15 15 -#define PT_R16 16 -#define PT_R17 17 -#define PT_R18 18 -#define PT_R19 19 -#define PT_R20 20 -#define PT_R21 21 -#define PT_R22 22 -#define PT_R23 23 -#define PT_R24 24 -#define PT_R25 25 -#define PT_R26 26 -#define PT_R27 27 -#define PT_R28 28 -#define PT_R29 29 -#define PT_R30 30 -#define PT_R31 31 - -#define PT_NIP 32 -#define PT_MSR 33 -#ifdef __KERNEL__ -#define PT_ORIG_R3 34 -#endif -#define PT_CTR 35 -#define PT_LNK 36 -#define PT_XER 37 -#define PT_CCR 38 -#define PT_SOFTE 39 -#define PT_TRAP 40 -#define PT_DAR 41 -#define PT_DSISR 42 -#define PT_RESULT 43 - -#define PT_FPR0 48 - -/* - * Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will - * have visibility to the asm-ppc/ptrace.h header instead of this one. - */ -#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */ - -#ifdef __KERNEL__ -#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */ -#endif - -#define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */ -#define PT_VSCR (PT_VR0 + 32*2 + 1) -#define PT_VRSAVE (PT_VR0 + 33*2) - -#ifdef __KERNEL__ -#define PT_VR0_32 164 /* each Vector reg occupies 4 slots in 32-bit */ -#define PT_VSCR_32 (PT_VR0 + 32*4 + 3) -#define PT_VRSAVE_32 (PT_VR0 + 33*4) -#endif - -/* - * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. - * The transfer totals 34 quadword. Quadwords 0-31 contain the - * corresponding vector registers. Quadword 32 contains the vscr as the - * last word (offset 12) within that quadword. Quadword 33 contains the - * vrsave as the first word (offset 0) within the quadword. - * - * This definition of the VMX state is compatible with the current PPC32 - * ptrace interface. This allows signal handling and ptrace to use the same - * structures. This also simplifies the implementation of a bi-arch - * (combined (32- and 64-bit) gdb. - */ -#define PTRACE_GETVRREGS 18 -#define PTRACE_SETVRREGS 19 - -/* - * While we dont have 64bit book E processors, we need to reserve the - * relevant ptrace calls for 32bit compatibility. - */ -#if 0 -#define PTRACE_GETEVRREGS 20 -#define PTRACE_SETEVRREGS 21 -#endif - -/* - * Get or set a debug register. The first 16 are DABR registers and the - * second 16 are IABR registers. - */ -#define PTRACE_GET_DEBUGREG 25 -#define PTRACE_SET_DEBUGREG 26 - -/* Additional PTRACE requests implemented on PowerPC. */ -#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ -#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ -#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ -#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ - -/* Calls to trace a 64bit program from a 32bit program */ -#define PPC_PTRACE_PEEKTEXT_3264 0x95 -#define PPC_PTRACE_PEEKDATA_3264 0x94 -#define PPC_PTRACE_POKETEXT_3264 0x93 -#define PPC_PTRACE_POKEDATA_3264 0x92 -#define PPC_PTRACE_PEEKUSR_3264 0x91 -#define PPC_PTRACE_POKEUSR_3264 0x90 - -#endif /* _PPC64_PTRACE_H */ -- cgit v1.2.3 From 879168ee51925f7e68165577fba8ef781ccfccb9 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 Nov 2005 15:32:07 +1100 Subject: powerpc: move include/asm-ppc64/ppc32.h to arch/powerpc/kernel It is only included by signal_32.c Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/ppc32.h | 138 ++++++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/signal_32.c | 2 +- include/asm-ppc64/ppc32.h | 138 ---------------------------------------- 3 files changed, 139 insertions(+), 139 deletions(-) create mode 100644 arch/powerpc/kernel/ppc32.h delete mode 100644 include/asm-ppc64/ppc32.h (limited to 'include') diff --git a/arch/powerpc/kernel/ppc32.h b/arch/powerpc/kernel/ppc32.h new file mode 100644 index 000000000000..90e562771791 --- /dev/null +++ b/arch/powerpc/kernel/ppc32.h @@ -0,0 +1,138 @@ +#ifndef _PPC64_PPC32_H +#define _PPC64_PPC32_H + +#include +#include +#include + +/* + * Data types and macros for providing 32b PowerPC support. + * + * 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. + */ + +/* These are here to support 32-bit syscalls on a 64-bit kernel. */ + +typedef struct compat_siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE32]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + compat_timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + compat_sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ + struct { + unsigned int _addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} compat_siginfo_t; + +#define __old_sigaction32 old_sigaction32 + +struct __old_sigaction32 { + compat_uptr_t sa_handler; + compat_old_sigset_t sa_mask; + unsigned int sa_flags; + compat_uptr_t sa_restorer; /* not used by Linux/SPARC yet */ +}; + + + +struct sigaction32 { + compat_uptr_t sa_handler; /* Really a pointer, but need to deal with 32 bits */ + unsigned int sa_flags; + compat_uptr_t sa_restorer; /* Another 32 bit pointer */ + compat_sigset_t sa_mask; /* A 32 bit mask */ +}; + +typedef struct sigaltstack_32 { + unsigned int ss_sp; + int ss_flags; + compat_size_t ss_size; +} stack_32_t; + +struct pt_regs32 { + unsigned int gpr[32]; + unsigned int nip; + unsigned int msr; + unsigned int orig_gpr3; /* Used for restarting system calls */ + unsigned int ctr; + unsigned int link; + unsigned int xer; + unsigned int ccr; + unsigned int mq; /* 601 only (not used at present) */ + unsigned int trap; /* Reason for being here */ + unsigned int dar; /* Fault registers */ + unsigned int dsisr; + unsigned int result; /* Result of a system call */ +}; + +struct sigcontext32 { + unsigned int _unused[4]; + int signal; + compat_uptr_t handler; + unsigned int oldmask; + compat_uptr_t regs; /* 4 byte pointer to the pt_regs32 structure. */ +}; + +struct mcontext32 { + elf_gregset_t32 mc_gregs; + elf_fpregset_t mc_fregs; + unsigned int mc_pad[2]; + elf_vrregset_t32 mc_vregs __attribute__((__aligned__(16))); +}; + +struct ucontext32 { + unsigned int uc_flags; + unsigned int uc_link; + stack_32_t uc_stack; + int uc_pad[7]; + compat_uptr_t uc_regs; /* points to uc_mcontext field */ + compat_sigset_t uc_sigmask; /* mask last for extensibility */ + /* glibc has 1024-bit signal masks, ours are 64-bit */ + int uc_maskext[30]; + int uc_pad2[3]; + struct mcontext32 uc_mcontext; +}; + +#endif /* _PPC64_PPC32_H */ diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 444c3e81884c..876c57c11365 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -43,7 +43,7 @@ #include #include #ifdef CONFIG_PPC64 -#include +#include "ppc32.h" #include #include #include diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h deleted file mode 100644 index 90e562771791..000000000000 --- a/include/asm-ppc64/ppc32.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef _PPC64_PPC32_H -#define _PPC64_PPC32_H - -#include -#include -#include - -/* - * Data types and macros for providing 32b PowerPC support. - * - * 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. - */ - -/* These are here to support 32-bit syscalls on a 64-bit kernel. */ - -typedef struct compat_siginfo { - int si_signo; - int si_errno; - int si_code; - - union { - int _pad[SI_PAD_SIZE32]; - - /* kill() */ - struct { - compat_pid_t _pid; /* sender's pid */ - compat_uid_t _uid; /* sender's uid */ - } _kill; - - /* POSIX.1b timers */ - struct { - compat_timer_t _tid; /* timer id */ - int _overrun; /* overrun count */ - compat_sigval_t _sigval; /* same as below */ - int _sys_private; /* not to be passed to user */ - } _timer; - - /* POSIX.1b signals */ - struct { - compat_pid_t _pid; /* sender's pid */ - compat_uid_t _uid; /* sender's uid */ - compat_sigval_t _sigval; - } _rt; - - /* SIGCHLD */ - struct { - compat_pid_t _pid; /* which child */ - compat_uid_t _uid; /* sender's uid */ - int _status; /* exit code */ - compat_clock_t _utime; - compat_clock_t _stime; - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ - struct { - unsigned int _addr; /* faulting insn/memory ref. */ - } _sigfault; - - /* SIGPOLL */ - struct { - int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - } _sifields; -} compat_siginfo_t; - -#define __old_sigaction32 old_sigaction32 - -struct __old_sigaction32 { - compat_uptr_t sa_handler; - compat_old_sigset_t sa_mask; - unsigned int sa_flags; - compat_uptr_t sa_restorer; /* not used by Linux/SPARC yet */ -}; - - - -struct sigaction32 { - compat_uptr_t sa_handler; /* Really a pointer, but need to deal with 32 bits */ - unsigned int sa_flags; - compat_uptr_t sa_restorer; /* Another 32 bit pointer */ - compat_sigset_t sa_mask; /* A 32 bit mask */ -}; - -typedef struct sigaltstack_32 { - unsigned int ss_sp; - int ss_flags; - compat_size_t ss_size; -} stack_32_t; - -struct pt_regs32 { - unsigned int gpr[32]; - unsigned int nip; - unsigned int msr; - unsigned int orig_gpr3; /* Used for restarting system calls */ - unsigned int ctr; - unsigned int link; - unsigned int xer; - unsigned int ccr; - unsigned int mq; /* 601 only (not used at present) */ - unsigned int trap; /* Reason for being here */ - unsigned int dar; /* Fault registers */ - unsigned int dsisr; - unsigned int result; /* Result of a system call */ -}; - -struct sigcontext32 { - unsigned int _unused[4]; - int signal; - compat_uptr_t handler; - unsigned int oldmask; - compat_uptr_t regs; /* 4 byte pointer to the pt_regs32 structure. */ -}; - -struct mcontext32 { - elf_gregset_t32 mc_gregs; - elf_fpregset_t mc_fregs; - unsigned int mc_pad[2]; - elf_vrregset_t32 mc_vregs __attribute__((__aligned__(16))); -}; - -struct ucontext32 { - unsigned int uc_flags; - unsigned int uc_link; - stack_32_t uc_stack; - int uc_pad[7]; - compat_uptr_t uc_regs; /* points to uc_mcontext field */ - compat_sigset_t uc_sigmask; /* mask last for extensibility */ - /* glibc has 1024-bit signal masks, ours are 64-bit */ - int uc_maskext[30]; - int uc_pad2[3]; - struct mcontext32 uc_mcontext; -}; - -#endif /* _PPC64_PPC32_H */ -- cgit v1.2.3 From 608f8b3cf3a7fbd009e6bf78e680ea04e6a4e46f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 Nov 2005 16:24:25 +1100 Subject: powerpc: merge sigcontext.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/sigcontext.h | 52 ++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/sigcontext.h | 15 ------------ include/asm-ppc64/sigcontext.h | 47 ------------------------------------ 3 files changed, 52 insertions(+), 62 deletions(-) create mode 100644 include/asm-powerpc/sigcontext.h delete mode 100644 include/asm-ppc/sigcontext.h delete mode 100644 include/asm-ppc64/sigcontext.h (limited to 'include') diff --git a/include/asm-powerpc/sigcontext.h b/include/asm-powerpc/sigcontext.h new file mode 100644 index 000000000000..165d630e1cf3 --- /dev/null +++ b/include/asm-powerpc/sigcontext.h @@ -0,0 +1,52 @@ +#ifndef _ASM_POWERPC_SIGCONTEXT_H +#define _ASM_POWERPC_SIGCONTEXT_H + +/* + * 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 +#ifdef __powerpc64__ +#include +#endif + +struct sigcontext { + unsigned long _unused[4]; + int signal; +#ifdef __powerpc64__ + int _pad0; +#endif + unsigned long handler; + unsigned long oldmask; + struct pt_regs __user *regs; +#ifdef __powerpc64__ + elf_gregset_t gp_regs; + elf_fpregset_t fp_regs; +/* + * To maintain compatibility with current implementations the sigcontext is + * extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t) + * followed by an unstructured (vmx_reserve) field of 69 doublewords. This + * allows the array of vector registers to be quadword aligned independent of + * the alignment of the containing sigcontext or ucontext. It is the + * responsibility of the code setting the sigcontext to set this pointer to + * either NULL (if this processor does not support the VMX feature) or the + * address of the first quadword within the allocated (vmx_reserve) area. + * + * The pointer (v_regs) of vector type (elf_vrreg_t) is type compatible with + * an array of 34 quadword entries (elf_vrregset_t). The entries with + * indexes 0-31 contain the corresponding vector registers. The entry with + * index 32 contains the vscr as the last word (offset 12) within the + * quadword. This allows the vscr to be stored as either a quadword (since + * it must be copied via a vector register to/from storage) or as a word. + * The entry with index 33 contains the vrsave as the first word (offset 0) + * within the quadword. + */ + elf_vrreg_t __user *v_regs; + long vmx_reserve[ELF_NVRREG+ELF_NVRREG+1]; +#endif +}; + +#endif /* _ASM_POWERPC_SIGCONTEXT_H */ diff --git a/include/asm-ppc/sigcontext.h b/include/asm-ppc/sigcontext.h deleted file mode 100644 index b7a417e0a921..000000000000 --- a/include/asm-ppc/sigcontext.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _ASM_PPC_SIGCONTEXT_H -#define _ASM_PPC_SIGCONTEXT_H - -#include -#include - -struct sigcontext { - unsigned long _unused[4]; - int signal; - unsigned long handler; - unsigned long oldmask; - struct pt_regs __user *regs; -}; - -#endif diff --git a/include/asm-ppc64/sigcontext.h b/include/asm-ppc64/sigcontext.h deleted file mode 100644 index 6f8aee768c5e..000000000000 --- a/include/asm-ppc64/sigcontext.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _ASM_PPC64_SIGCONTEXT_H -#define _ASM_PPC64_SIGCONTEXT_H - -/* - * 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 - - -struct sigcontext { - unsigned long _unused[4]; - int signal; - int _pad0; - unsigned long handler; - unsigned long oldmask; - struct pt_regs __user *regs; - elf_gregset_t gp_regs; - elf_fpregset_t fp_regs; -/* - * To maintain compatibility with current implementations the sigcontext is - * extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t) - * followed by an unstructured (vmx_reserve) field of 69 doublewords. This - * allows the array of vector registers to be quadword aligned independent of - * the alignment of the containing sigcontext or ucontext. It is the - * responsibility of the code setting the sigcontext to set this pointer to - * either NULL (if this processor does not support the VMX feature) or the - * address of the first quadword within the allocated (vmx_reserve) area. - * - * The pointer (v_regs) of vector type (elf_vrreg_t) is type compatible with - * an array of 34 quadword entries (elf_vrregset_t). The entries with - * indexes 0-31 contain the corresponding vector registers. The entry with - * index 32 contains the vscr as the last word (offset 12) within the - * quadword. This allows the vscr to be stored as either a quadword (since - * it must be copied via a vector register to/from storage) or as a word. - * The entry with index 33 contains the vrsave as the first word (offset 0) - * within the quadword. - */ - elf_vrreg_t __user *v_regs; - long vmx_reserve[ELF_NVRREG+ELF_NVRREG+1]; -}; - -#endif /* _ASM_PPC64_SIGCONTEXT_H */ -- cgit v1.2.3 From 38dc16186433ba961ace39c97ac6f7071250f981 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 2 Nov 2005 12:46:28 -0200 Subject: [PATCH] ppc32 8xx: Fix harmless warning in 8xx_io/commproc.c Signed-off-by: Paul Mackerras --- include/asm-ppc/commproc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h index 5bbb8e2c1c6d..973e60908234 100644 --- a/include/asm-ppc/commproc.h +++ b/include/asm-ppc/commproc.h @@ -83,6 +83,8 @@ extern uint m8xx_cpm_hostalloc(uint size); extern int m8xx_cpm_hostfree(uint start); extern void m8xx_cpm_hostdump(void); +extern void cpm_load_patch(volatile immap_t *immr); + /* Buffer descriptors used by many of the CPM protocols. */ typedef struct cpm_buf_desc { -- cgit v1.2.3 From 7f23292d5a6525a133d7cb8f2f33df39dd069822 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 3 Nov 2005 10:13:58 +1100 Subject: [PATCH] powerpc: Keep fixing merged ipcbuf.h Oops, replacing the two u64s in struct ipc64_perm with __u32s changed the alignment of that structure, which could mess up userspace. Revert to using two unsigned long longs (which is what ppc32 had originally). ppc64 orignally had two unsigned longs, but long long is the same size on 64 bit, so this should be ok there too. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/ipcbuf.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-powerpc/ipcbuf.h b/include/asm-powerpc/ipcbuf.h index 71382c1ec6e3..2c3e1d94db1d 100644 --- a/include/asm-powerpc/ipcbuf.h +++ b/include/asm-powerpc/ipcbuf.h @@ -27,7 +27,8 @@ struct ipc64_perm __kernel_mode_t mode; unsigned int seq; unsigned int __pad1; - __u32 __unused[4]; + unsigned long long __unused1; + unsigned long long __unused2; }; #endif /* _ASM_POWERPC_IPCBUF_H */ -- cgit v1.2.3 From 5adb83c2fa136e14172b1a65b0f8aa28f2cb9f62 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 3 Nov 2005 16:59:17 +1100 Subject: powerpc: merge ucontext.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/ucontext.h | 40 ++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/ucontext.h | 27 --------------------------- include/asm-ppc64/ucontext.h | 22 ---------------------- 3 files changed, 40 insertions(+), 49 deletions(-) create mode 100644 include/asm-powerpc/ucontext.h delete mode 100644 include/asm-ppc/ucontext.h delete mode 100644 include/asm-ppc64/ucontext.h (limited to 'include') diff --git a/include/asm-powerpc/ucontext.h b/include/asm-powerpc/ucontext.h new file mode 100644 index 000000000000..d9a4ddf0cc86 --- /dev/null +++ b/include/asm-powerpc/ucontext.h @@ -0,0 +1,40 @@ +#ifndef _ASM_POWERPC_UCONTEXT_H +#define _ASM_POWERPC_UCONTEXT_H + +#ifdef __powerpc64__ +#include +#else +#include +#endif +#include + +#ifndef __powerpc64__ +struct mcontext { + elf_gregset_t mc_gregs; + elf_fpregset_t mc_fregs; + unsigned long mc_pad[2]; + elf_vrregset_t mc_vregs __attribute__((__aligned__(16))); +}; +#endif + +struct ucontext { + unsigned long uc_flags; + struct ucontext __user *uc_link; + stack_t uc_stack; +#ifndef __powerpc64__ + int uc_pad[7]; + struct mcontext __user *uc_regs;/* points to uc_mcontext field */ +#endif + sigset_t uc_sigmask; + /* glibc has 1024-bit signal masks, ours are 64-bit */ +#ifdef __powerpc64__ + sigset_t __unused[15]; /* Allow for uc_sigmask growth */ + struct sigcontext uc_mcontext; /* last for extensibility */ +#else + int uc_maskext[30]; + int uc_pad2[3]; + struct mcontext uc_mcontext; +#endif +}; + +#endif /* _ASM_POWERPC_UCONTEXT_H */ diff --git a/include/asm-ppc/ucontext.h b/include/asm-ppc/ucontext.h deleted file mode 100644 index 664bc984d51f..000000000000 --- a/include/asm-ppc/ucontext.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _ASMPPC_UCONTEXT_H -#define _ASMPPC_UCONTEXT_H - -#include -#include - -struct mcontext { - elf_gregset_t mc_gregs; - elf_fpregset_t mc_fregs; - unsigned long mc_pad[2]; - elf_vrregset_t mc_vregs __attribute__((__aligned__(16))); -}; - -struct ucontext { - unsigned long uc_flags; - struct ucontext __user *uc_link; - stack_t uc_stack; - int uc_pad[7]; - struct mcontext __user *uc_regs;/* points to uc_mcontext field */ - sigset_t uc_sigmask; - /* glibc has 1024-bit signal masks, ours are 64-bit */ - int uc_maskext[30]; - int uc_pad2[3]; - struct mcontext uc_mcontext; -}; - -#endif /* !_ASMPPC_UCONTEXT_H */ diff --git a/include/asm-ppc64/ucontext.h b/include/asm-ppc64/ucontext.h deleted file mode 100644 index ef8cc5b37542..000000000000 --- a/include/asm-ppc64/ucontext.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _ASMPPC64_UCONTEXT_H -#define _ASMPPC64_UCONTEXT_H - -#include - -/* - * 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. - */ - -struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - sigset_t uc_sigmask; - sigset_t __unsued[15]; /* Allow for uc_sigmask growth */ - struct sigcontext uc_mcontext; /* last for extensibility */ -}; - -#endif /* _ASMPPC64_UCONTEXT_H */ -- cgit v1.2.3 From c87ef1171db207d9d19f87ad12db92974d95c466 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 Nov 2005 17:57:53 +1100 Subject: powerpc: Add helper functions for synthesising instructions at runtime There's a few places already, and soon will be more, where we synthesise branch instructions at runtime. Rather than doing it by hand in each case, it would make sense to have one implementation. Signed-off-by: Michael Ellerman --- include/asm-powerpc/system.h | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'include') diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 5b2ecbc47907..b5da0b851e02 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -359,5 +359,53 @@ extern void reloc_got2(unsigned long); #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) +static inline void create_instruction(unsigned long addr, unsigned int instr) +{ + unsigned int *p; + p = (unsigned int *)addr; + *p = instr; + asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (p)); +} + +/* Flags for create_branch: + * "b" == create_branch(addr, target, 0); + * "ba" == create_branch(addr, target, BRANCH_ABSOLUTE); + * "bl" == create_branch(addr, target, BRANCH_SET_LINK); + * "bla" == create_branch(addr, target, BRANCH_ABSOLUTE | BRANCH_SET_LINK); + */ +#define BRANCH_SET_LINK 0x1 +#define BRANCH_ABSOLUTE 0x2 + +static inline void create_branch(unsigned long addr, + unsigned long target, int flags) +{ + unsigned int instruction; + + if (! (flags & BRANCH_ABSOLUTE)) + target = target - addr; + + /* Mask out the flags and target, so they don't step on each other. */ + instruction = 0x48000000 | (flags & 0x3) | (target & 0x03FFFFFC); + + create_instruction(addr, instruction); +} + +static inline void create_function_call(unsigned long addr, void * func) +{ + unsigned long func_addr; + +#ifdef CONFIG_PPC64 + /* + * On PPC64 the function pointer actually points to the function's + * descriptor. The first entry in the descriptor is the address + * of the function text. + */ + func_addr = *(unsigned long *)func; +#else + func_addr = (unsigned long)func; +#endif + create_branch(addr, func_addr, BRANCH_SET_LINK); +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_SYSTEM_H */ -- cgit v1.2.3 From 40765d2b8b86446b4ac8ec880cf4fdf56ce4ae7e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 Nov 2005 19:34:38 +1100 Subject: powerpc: Cleanup vpa code register_vpa() doesn't actually do a VPA register call it just uses the flags you pass it, so rename it to vpa_call() to be clearer. We can then define register_vpa() and unregister_vpa() which are both simple wrappers around vpa_call(). (we'll need unregister_vpa() for kexec soon) We can then cleanup vpa_init(), and because vpa_init() is only called from platforms/pseries we remove the definition in asm-ppc64/smp.h. Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/lpar.c | 10 +++------- arch/powerpc/platforms/pseries/plpar_wrappers.h | 19 ++++++++++++++++--- include/asm-ppc64/smp.h | 8 -------- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 8a7bda3db677..e384a5a91796 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -261,22 +261,18 @@ out: void vpa_init(int cpu) { int hwcpu = get_hard_smp_processor_id(cpu); - unsigned long vpa = (unsigned long)&(paca[cpu].lppaca); + unsigned long vpa = __pa(&paca[cpu].lppaca); long ret; - unsigned long flags; - - /* Register the Virtual Processor Area (VPA) */ - flags = 1UL << (63 - 18); if (cpu_has_feature(CPU_FTR_ALTIVEC)) paca[cpu].lppaca.vmxregs_in_use = 1; - ret = register_vpa(flags, hwcpu, __pa(vpa)); + ret = register_vpa(hwcpu, vpa); if (ret) printk(KERN_ERR "WARNING: vpa_init: VPA registration for " "cpu %d (hw %d) of area %lx returns %ld\n", - cpu, hwcpu, __pa(vpa), ret); + cpu, hwcpu, vpa, ret); } long pSeries_lpar_hpte_insert(unsigned long hpte_group, diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 2457be2e217e..382f8c5b0e7c 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -21,13 +21,26 @@ static inline long cede_processor(void) return 0; } -static inline long register_vpa(unsigned long flags, unsigned long proc, +static inline long vpa_call(unsigned long flags, unsigned long cpu, unsigned long vpa) { - return plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); + /* flags are in bits 16-18 (counting from most significant bit) */ + flags = flags << (63 - 18); + + return plpar_hcall_norets(H_REGISTER_VPA, flags, cpu, vpa); +} + +static inline long unregister_vpa(unsigned long cpu, unsigned long vpa) +{ + return vpa_call(0x5, cpu, vpa); +} + +static inline long register_vpa(unsigned long cpu, unsigned long vpa) +{ + return vpa_call(0x1, cpu, vpa); } -void vpa_init(int cpu); +extern void vpa_init(int cpu); static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex, unsigned long avpn, unsigned long *old_pteh_ret, diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h index 0f42fcc1900b..46c04046952d 100644 --- a/include/asm-ppc64/smp.h +++ b/include/asm-ppc64/smp.h @@ -85,14 +85,6 @@ extern void smp_generic_take_timebase(void); extern struct smp_ops_t *smp_ops; -#ifdef CONFIG_PPC_PSERIES -void vpa_init(int cpu); -#else -static inline void vpa_init(int cpu) -{ -} -#endif /* CONFIG_PPC_PSERIES */ - #endif /* __ASSEMBLY__ */ #endif /* !(_PPC64_SMP_H) */ -- cgit v1.2.3 From 089311e117adb8ffe13984d122e33287ffa8c7ec Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 3 Nov 2005 11:04:53 +0000 Subject: [ARM] Fix another build error with IOP3xx platforms ld doesn't like comments starting with // in its scripts Signed-off-by: Russell King --- include/asm-arm/arch-iop3xx/iop321.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-iop3xx/iop321.h b/include/asm-arm/arch-iop3xx/iop321.h index 200621ff3690..f8df778a356f 100644 --- a/include/asm-arm/arch-iop3xx/iop321.h +++ b/include/asm-arm/arch-iop3xx/iop321.h @@ -40,7 +40,7 @@ #define IOP321_PCI_UPPER_IO_BA (IOP321_PCI_LOWER_IO_BA + IOP321_PCI_IO_WINDOW_SIZE - 1) #define IOP321_PCI_IO_OFFSET (IOP321_PCI_LOWER_IO_VA - IOP321_PCI_LOWER_IO_BA) -//#define IOP321_PCI_MEM_WINDOW_SIZE (~*IOP321_IALR1 + 1) +/* #define IOP321_PCI_MEM_WINDOW_SIZE (~*IOP321_IALR1 + 1) */ #define IOP321_PCI_MEM_WINDOW_SIZE 0x04000000 /* 64M outbound window */ #define IOP321_PCI_LOWER_MEM_PA 0x80000000 #define IOP321_PCI_LOWER_MEM_BA (*IOP321_OMWTVR0) -- cgit v1.2.3 From 7e5e6e9a509c4ed2973a345ec7ffb96577f42e26 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 3 Nov 2005 20:32:45 +0000 Subject: [ARM SMP] Do not clear cpu_vm_mask for VIPT caches Since we do not invalidate TLBs/caches on MM switches, we should not clear the cpu_vm_mask for the CPU. Signed-off-by: Russell King --- include/asm-arm/mmu_context.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h index 4af9c411c617..57b8def83d41 100644 --- a/include/asm-arm/mmu_context.h +++ b/include/asm-arm/mmu_context.h @@ -86,7 +86,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, cpu_set(cpu, next->cpu_vm_mask); check_context(next); cpu_switch_mm(next->pgd, next); - cpu_clear(cpu, prev->cpu_vm_mask); + if (cache_is_vivt()) + cpu_clear(cpu, prev->cpu_vm_mask); } } -- cgit v1.2.3 From 9a0f78f63bc05d195aab781486ed57d1418d5f59 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 4 Nov 2005 10:20:27 +1100 Subject: powerpc: merge tlb.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/tlb.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/tlb.h | 57 -------------------------------------- include/asm-ppc64/tlb.h | 39 -------------------------- 3 files changed, 70 insertions(+), 96 deletions(-) create mode 100644 include/asm-powerpc/tlb.h delete mode 100644 include/asm-ppc/tlb.h delete mode 100644 include/asm-ppc64/tlb.h (limited to 'include') diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h new file mode 100644 index 000000000000..56659f121779 --- /dev/null +++ b/include/asm-powerpc/tlb.h @@ -0,0 +1,70 @@ +/* + * TLB shootdown specifics for powerpc + * + * Copyright (C) 2002 Anton Blanchard, IBM Corp. + * Copyright (C) 2002 Paul Mackerras, IBM Corp. + * + * 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. + */ +#ifndef _ASM_POWERPC_TLB_H +#define _ASM_POWERPC_TLB_H + +#include +#ifndef __powerpc64__ +#include +#endif +#include +#include +#ifndef __powerpc64__ +#include +#include +#endif + +struct mmu_gather; + +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) + +#if !defined(CONFIG_PPC_STD_MMU) + +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +#elif defined(__powerpc64__) + +extern void pte_free_finish(void); + +static inline void tlb_flush(struct mmu_gather *tlb) +{ + flush_tlb_pending(); + pte_free_finish(); +} + +#else + +extern void tlb_flush(struct mmu_gather *tlb); + +#endif + +/* Get the generic bits... */ +#include + +#if !defined(CONFIG_PPC_STD_MMU) || defined(__powerpc64__) + +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) + +#else +extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, + unsigned long address); + +static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, + unsigned long address) +{ + if (pte_val(*ptep) & _PAGE_HASHPTE) + flush_hash_entry(tlb->mm, ptep, address); +} + +#endif +#endif /* __ASM_POWERPC_TLB_H */ diff --git a/include/asm-ppc/tlb.h b/include/asm-ppc/tlb.h deleted file mode 100644 index 2c142c5d8584..000000000000 --- a/include/asm-ppc/tlb.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * TLB shootdown specifics for PPC - * - * Copyright (C) 2002 Paul Mackerras, IBM Corp. - * - * 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. - */ -#ifndef _PPC_TLB_H -#define _PPC_TLB_H - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PPC_STD_MMU -/* Classic PPC with hash-table based MMU... */ - -struct mmu_gather; -extern void tlb_flush(struct mmu_gather *tlb); - -/* Get the generic bits... */ -#include - -/* Nothing needed here in fact... */ -#define tlb_start_vma(tlb, vma) do { } while (0) -#define tlb_end_vma(tlb, vma) do { } while (0) - -extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, - unsigned long address); - -static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, - unsigned long address) -{ - if (pte_val(*ptep) & _PAGE_HASHPTE) - flush_hash_entry(tlb->mm, ptep, address); -} - -#else -/* Embedded PPC with software-loaded TLB, very simple... */ - -#define tlb_start_vma(tlb, vma) do { } while (0) -#define tlb_end_vma(tlb, vma) do { } while (0) -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) - -/* Get the generic bits... */ -#include - -#endif /* CONFIG_PPC_STD_MMU */ - -#endif /* __PPC_TLB_H */ diff --git a/include/asm-ppc64/tlb.h b/include/asm-ppc64/tlb.h deleted file mode 100644 index 97cb696ce68d..000000000000 --- a/include/asm-ppc64/tlb.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * TLB shootdown specifics for PPC64 - * - * Copyright (C) 2002 Anton Blanchard, IBM Corp. - * Copyright (C) 2002 Paul Mackerras, IBM Corp. - * - * 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. - */ -#ifndef _PPC64_TLB_H -#define _PPC64_TLB_H - -#include - -struct mmu_gather; - -extern void pte_free_finish(void); - -static inline void tlb_flush(struct mmu_gather *tlb) -{ - flush_tlb_pending(); - pte_free_finish(); -} - -/* Avoid pulling in another include just for this */ -#define check_pgt_cache() do { } while (0) - -/* Get the generic bits... */ -#include - -/* Nothing needed here in fact... */ -#define tlb_start_vma(tlb, vma) do { } while (0) -#define tlb_end_vma(tlb, vma) do { } while (0) - -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) - -#endif /* _PPC64_TLB_H */ -- cgit v1.2.3 From b8f510219edc719d4c305918e16edc578bcfc16f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 4 Nov 2005 12:09:42 +1100 Subject: powerpc: Implement smp_release_cpus() in C not asm There's no reason for smp_release_cpus() to be asm, and most people can make more sense of C code. Add an extern declaration to smp.h and remove the custom one in machine_kexec.c Signed-off-by: Michael Ellerman Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/head_64.S | 18 ------------------ arch/powerpc/kernel/setup_64.c | 23 +++++++++++++++++++++-- arch/ppc64/kernel/head.S | 18 ------------------ arch/ppc64/kernel/machine_kexec.c | 1 - include/asm-ppc64/smp.h | 1 + 5 files changed, 22 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index ba30e3177b05..45d81976987f 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1914,24 +1914,6 @@ _GLOBAL(hmt_start_secondary) blr #endif -#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP) -_GLOBAL(smp_release_cpus) - /* All secondary cpus are spinning on a common - * spinloop, release them all now so they can start - * to spin on their individual paca spinloops. - * For non SMP kernels, the secondary cpus never - * get out of the common spinloop. - * XXX This does nothing useful on iSeries, secondaries are - * already waiting on their paca. - */ - li r3,1 - LOADADDR(r5,__secondary_hold_spinloop) - std r3,0(r5) - sync - blr -#endif /* CONFIG_SMP */ - - /* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the bss, which is page-aligned. diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index d4a3c5dd1a21..275d86ddd612 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -103,8 +103,6 @@ extern void htab_initialize(void); extern void early_init_devtree(void *flat_dt); extern void unflatten_device_tree(void); -extern void smp_release_cpus(void); - int have_of = 1; int boot_cpuid = 0; int boot_cpuid_phys = 0; @@ -400,6 +398,27 @@ void __init early_setup(unsigned long dt_ptr) } +#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) +void smp_release_cpus(void) +{ + extern unsigned long __secondary_hold_spinloop; + + DBG(" -> smp_release_cpus()\n"); + + /* All secondary cpus are spinning on a common spinloop, release them + * all now so they can start to spin on their individual paca + * spinloops. For non SMP kernels, the secondary cpus never get out + * of the common spinloop. + * This is useless but harmless on iSeries, secondaries are already + * waiting on their paca spinloops. */ + + __secondary_hold_spinloop = 1; + mb(); + + DBG(" <- smp_release_cpus()\n"); +} +#endif /* CONFIG_SMP || CONFIG_KEXEC */ + /* * Initialize some remaining members of the ppc64_caches and systemcfg structures * (at least until we get rid of them completely). This is mostly some diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 0b65efe1682e..db1cf397be2d 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -1914,24 +1914,6 @@ _GLOBAL(hmt_start_secondary) blr #endif -#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP) -_GLOBAL(smp_release_cpus) - /* All secondary cpus are spinning on a common - * spinloop, release them all now so they can start - * to spin on their individual paca spinloops. - * For non SMP kernels, the secondary cpus never - * get out of the common spinloop. - * XXX This does nothing useful on iSeries, secondaries are - * already waiting on their paca. - */ - li r3,1 - LOADADDR(r5,__secondary_hold_spinloop) - std r3,0(r5) - sync - blr -#endif /* CONFIG_SMP */ - - /* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the bss, which is page-aligned. diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index bf7cc4f8210f..ff8679f260f3 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -244,7 +244,6 @@ static void kexec_prepare_cpus(void) static void kexec_prepare_cpus(void) { - extern void smp_release_cpus(void); /* * move the secondarys to us so that we can copy * the new kernel 0-0x100 safely diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h index 46c04046952d..ba0f5c8bbb22 100644 --- a/include/asm-ppc64/smp.h +++ b/include/asm-ppc64/smp.h @@ -79,6 +79,7 @@ extern int smt_enabled_at_boot; extern int smp_mpic_probe(void); extern void smp_mpic_setup_cpu(int cpu); extern void smp_generic_kick_cpu(int nr); +extern void smp_release_cpus(void); extern void smp_generic_give_timebase(void); extern void smp_generic_take_timebase(void); -- cgit v1.2.3 From 30415f6a63f3383a18e9adf7c144acabe6893f63 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 Nov 2005 21:10:48 +1100 Subject: powerpc: Fix random memory corruption in merged elf.h The merged verison of ELF_CORE_COPY_REGS is basically the PPC64 version, with a memset that came from PPC and a few types abstracted out into #defines. But it's not _quite_ right. The first problem is we calculate the number of registers with: nregs = sizeof(struct pt_regs) / sizeof(ELF_GREG_TYPE) For a 32-bit process on a 64-bit kernel that's bogus because the registers are 64 bits, but ELF_GREG_TYPE is u32, so nregs == 88 which is wrong. The other problem is the memset, which assumes a struct pt_regs is smaller than a struct elf_regs. For a 32-bit process on a 64-bit kernel that's false. The fix is to calculate the number of regs using sizeof(unsigned long), which should always be right, and just memset the whole damn thing _before_ copying the registers in. Signed-off-by: Michael Ellerman --- include/asm-powerpc/elf.h | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index d22b10021b5d..d140577d0a05 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -178,18 +178,22 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32]; static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs, struct pt_regs *regs) { - int i; - int gprs = sizeof(struct pt_regs)/sizeof(ELF_GREG_TYPE); + int i, nregs; - if (gprs > ELF_NGREG) - gprs = ELF_NGREG; + memset((void *)elf_regs, 0, sizeof(elf_gregset_t)); - for (i=0; i < gprs; i++) - elf_regs[i] = (elf_greg_t)((ELF_GREG_TYPE *)regs)[i]; - - memset((char *)(elf_regs) + sizeof(struct pt_regs), 0, \ - sizeof(elf_gregset_t) - sizeof(struct pt_regs)); + /* Our registers are always unsigned longs, whether we're a 32 bit + * process or 64 bit, on either a 64 bit or 32 bit kernel. + * Don't use ELF_GREG_TYPE here. */ + nregs = sizeof(struct pt_regs) / sizeof(unsigned long); + if (nregs > ELF_NGREG) + nregs = ELF_NGREG; + for (i = 0; i < nregs; i++) { + /* This will correctly truncate 64 bit registers to 32 bits + * for a 32 bit process on a 64 bit kernel. */ + elf_regs[i] = (elf_greg_t)((ELF_GREG_TYPE *)regs)[i]; + } } #define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs); -- cgit v1.2.3 From 1970282f3b453b7aac3b192a44705dcb5277fd82 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 4 Nov 2005 16:58:59 +1100 Subject: powerpc: merge tlbflush.h Signed-off-by: Stephen Rothwell --- include/asm-powerpc/tlbflush.h | 146 +++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/tlbflush.h | 115 -------------------------------- include/asm-ppc64/tlbflush.h | 52 --------------- 3 files changed, 146 insertions(+), 167 deletions(-) create mode 100644 include/asm-powerpc/tlbflush.h delete mode 100644 include/asm-ppc/tlbflush.h delete mode 100644 include/asm-ppc64/tlbflush.h (limited to 'include') diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h new file mode 100644 index 000000000000..ca3655672bbc --- /dev/null +++ b/include/asm-powerpc/tlbflush.h @@ -0,0 +1,146 @@ +#ifndef _ASM_POWERPC_TLBFLUSH_H +#define _ASM_POWERPC_TLBFLUSH_H +/* + * TLB flushing: + * + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables + * + * 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. + */ +#ifdef __KERNEL__ + +#include + +struct mm_struct; + +#ifdef CONFIG_PPC64 + +#include +#include + +#define PPC64_TLB_BATCH_NR 192 + +struct ppc64_tlb_batch { + unsigned long index; + struct mm_struct *mm; + pte_t pte[PPC64_TLB_BATCH_NR]; + unsigned long vaddr[PPC64_TLB_BATCH_NR]; + unsigned int large; +}; +DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); + +extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); + +static inline void flush_tlb_pending(void) +{ + struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch); + + if (batch->index) + __flush_tlb_pending(batch); + put_cpu_var(ppc64_tlb_batch); +} + +extern void flush_hash_page(unsigned long va, pte_t pte, int local); +void flush_hash_range(unsigned long number, int local); + +#else /* CONFIG_PPC64 */ + +#include + +extern void _tlbie(unsigned long address); +extern void _tlbia(void); + +/* + * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range & + * flush_tlb_kernel_range are best implemented as tlbia vs + * specific tlbie's + */ + +#if (defined(CONFIG_4xx) && !defined(CONFIG_44x)) || defined(CONFIG_8xx) +#define flush_tlb_pending() asm volatile ("tlbia; sync" : : : "memory") +#elif defined(CONFIG_4xx) || defined(CONFIG_FSL_BOOKE) +#define flush_tlb_pending() _tlbia() +#endif + +/* + * This gets called at the end of handling a page fault, when + * the kernel has put a new PTE into the page table for the process. + * We use it to ensure coherency between the i-cache and d-cache + * for the page which has just been mapped in. + * On machines which use an MMU hash table, we use this to put a + * corresponding HPTE into the hash table ahead of time, instead of + * waiting for the inevitable extra hash-table miss exception. + */ +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); + +#endif /* CONFIG_PPC64 */ + +#if defined(CONFIG_PPC64) || defined(CONFIG_4xx) || \ + defined(CONFIG_FSL_BOOKE) || defined(CONFIG_8xx) + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + flush_tlb_pending(); +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ +#ifdef CONFIG_PPC64 + flush_tlb_pending(); +#else + _tlbie(vmaddr); +#endif +} + +static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, + unsigned long vmaddr) +{ +#ifndef CONFIG_PPC64 + _tlbie(vmaddr); +#endif +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + flush_tlb_pending(); +} + +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ + flush_tlb_pending(); +} + +#else /* 6xx, 7xx, 7xxx cpus */ + +extern void flush_tlb_mm(struct mm_struct *mm); +extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); +extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr); +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); + +#endif + +/* + * This is called in munmap when we have freed up some page-table + * pages. We don't need to do anything here, there's nothing special + * about our page-table pages. -- paulus + */ +static inline void flush_tlb_pgtables(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ +} + +#endif /*__KERNEL__ */ +#endif /* _ASM_POWERPC_TLBFLUSH_H */ diff --git a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h deleted file mode 100644 index 9afee4ffc835..000000000000 --- a/include/asm-ppc/tlbflush.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * include/asm-ppc/tlbflush.h - * - * 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. - */ -#ifdef __KERNEL__ -#ifndef _PPC_TLBFLUSH_H -#define _PPC_TLBFLUSH_H - -#include -#include - -extern void _tlbie(unsigned long address); -extern void _tlbia(void); - -#if defined(CONFIG_4xx) - -#ifndef CONFIG_44x -#define __tlbia() asm volatile ("sync; tlbia; isync" : : : "memory") -#else -#define __tlbia _tlbia -#endif - -static inline void flush_tlb_mm(struct mm_struct *mm) - { __tlbia(); } -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) - { _tlbie(vmaddr); } -static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, - unsigned long vmaddr) - { _tlbie(vmaddr); } -static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) - { __tlbia(); } -static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) - { __tlbia(); } - -#elif defined(CONFIG_FSL_BOOKE) - -/* TODO: determine if flush_tlb_range & flush_tlb_kernel_range - * are best implemented as tlbia vs specific tlbie's */ - -#define __tlbia() _tlbia() - -static inline void flush_tlb_mm(struct mm_struct *mm) - { __tlbia(); } -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) - { _tlbie(vmaddr); } -static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, - unsigned long vmaddr) - { _tlbie(vmaddr); } -static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) - { __tlbia(); } -static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) - { __tlbia(); } - -#elif defined(CONFIG_8xx) -#define __tlbia() asm volatile ("tlbia; sync" : : : "memory") - -static inline void flush_tlb_mm(struct mm_struct *mm) - { __tlbia(); } -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) - { _tlbie(vmaddr); } -static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, - unsigned long vmaddr) - { _tlbie(vmaddr); } -static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) - { __tlbia(); } -static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) - { __tlbia(); } - -#else /* 6xx, 7xx, 7xxx cpus */ -struct mm_struct; -struct vm_area_struct; -extern void flush_tlb_mm(struct mm_struct *mm); -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr); -extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); -#endif - -/* - * This is called in munmap when we have freed up some page-table - * pages. We don't need to do anything here, there's nothing special - * about our page-table pages. -- paulus - */ -static inline void flush_tlb_pgtables(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ -} - -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to ensure coherency between the i-cache and d-cache - * for the page which has just been mapped in. - * On machines which use an MMU hash table, we use this to put a - * corresponding HPTE into the hash table ahead of time, instead of - * waiting for the inevitable extra hash-table miss exception. - */ -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); - -#endif /* _PPC_TLBFLUSH_H */ -#endif /*__KERNEL__ */ diff --git a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h deleted file mode 100644 index 626f505c6ee3..000000000000 --- a/include/asm-ppc64/tlbflush.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _PPC64_TLBFLUSH_H -#define _PPC64_TLBFLUSH_H - -/* - * TLB flushing: - * - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB - * - flush_tlb_range(vma, start, end) flushes a range of pages - * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages - * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables - */ - -#include -#include - -#define PPC64_TLB_BATCH_NR 192 - -struct mm_struct; -struct ppc64_tlb_batch { - unsigned long index; - struct mm_struct *mm; - pte_t pte[PPC64_TLB_BATCH_NR]; - unsigned long vaddr[PPC64_TLB_BATCH_NR]; - unsigned int large; -}; -DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); - -extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); - -static inline void flush_tlb_pending(void) -{ - struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch); - - if (batch->index) - __flush_tlb_pending(batch); - put_cpu_var(ppc64_tlb_batch); -} - -#define flush_tlb_mm(mm) flush_tlb_pending() -#define flush_tlb_page(vma, addr) flush_tlb_pending() -#define flush_tlb_page_nohash(vma, addr) do { } while (0) -#define flush_tlb_range(vma, start, end) \ - do { (void)(start); flush_tlb_pending(); } while (0) -#define flush_tlb_kernel_range(start, end) flush_tlb_pending() -#define flush_tlb_pgtables(mm, start, end) do { } while (0) - -extern void flush_hash_page(unsigned long va, pte_t pte, int local); -void flush_hash_range(unsigned long number, int local); - -#endif /* _PPC64_TLBFLUSH_H */ -- cgit v1.2.3 From 2ba71978c04d4dba983b4fc658f82eae164c2bca Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Thu, 29 Sep 2005 12:58:24 +0200 Subject: [ALSA] Removing obsolete AC97_SHARED_TYPES This patch cleans last ac97 audio/modem codec interception in initialization procedures (ac97_mixer_new()) and removes obsolete SHARED_TYPE 'locking' which prevents from AMC codecs to function correctly. Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 10 ---------- sound/pci/ac97/ac97_codec.c | 38 ++------------------------------------ sound/pci/atiixp.c | 1 - sound/pci/atiixp_modem.c | 1 - sound/pci/intel8x0.c | 1 - sound/pci/intel8x0m.c | 1 - sound/pci/via82xx.c | 2 +- sound/pci/via82xx_modem.c | 1 - 8 files changed, 3 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index d11f34832a97..7f0ca79d6c98 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -387,15 +387,6 @@ #define AC97_RATES_MIC_ADC 4 #define AC97_RATES_SPDIF 5 -/* shared controllers */ -enum { - AC97_SHARED_TYPE_NONE, - AC97_SHARED_TYPE_ICH, - AC97_SHARED_TYPE_ATIIXP, - AC97_SHARED_TYPE_VIA, - AC97_SHARED_TYPES -}; - /* * */ @@ -468,7 +459,6 @@ struct _snd_ac97_bus { unsigned short used_slots[2][4]; /* actually used PCM slots */ unsigned short pcms_count; /* count of PCMs */ struct ac97_pcm *pcms; - unsigned int shared_type; /* type of shared controller betwen audio and modem */ ac97_t *codec[4]; snd_info_entry_t *proc; }; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 41fc290149ed..56549add80a8 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -220,12 +220,6 @@ const char *snd_ac97_stereo_enhancements[] = /* 31 */ "Reserved 31" }; -/* - * Shared AC97 controllers (ICH, ATIIXP...) - */ -static DECLARE_MUTEX(shared_codec_mutex); -static ac97_t *shared_codec[AC97_SHARED_TYPES][4]; - /* * I/O routines @@ -996,14 +990,8 @@ static int snd_ac97_free(ac97_t *ac97) { if (ac97) { snd_ac97_proc_done(ac97); - if (ac97->bus) { + if (ac97->bus) ac97->bus->codec[ac97->num] = NULL; - if (ac97->bus->shared_type) { - down(&shared_codec_mutex); - shared_codec[ac97->bus->shared_type-1][ac97->num] = NULL; - up(&shared_codec_mutex); - } - } if (ac97->private_free) ac97->private_free(ac97); kfree(ac97); @@ -1889,21 +1877,6 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) snd_assert(bus != NULL && template != NULL, return -EINVAL); snd_assert(template->num < 4 && bus->codec[template->num] == NULL, return -EINVAL); - snd_assert(bus->shared_type <= AC97_SHARED_TYPES, return -EINVAL); - if (bus->shared_type) { - /* already shared? */ - down(&shared_codec_mutex); - ac97 = shared_codec[bus->shared_type-1][template->num]; - if (ac97) { - if ((ac97_is_audio(ac97) && (template->scaps & AC97_SCAP_SKIP_AUDIO)) || - (ac97_is_modem(ac97) && (template->scaps & AC97_SCAP_SKIP_MODEM))) { - up(&shared_codec_mutex); - return -EACCES; /* skip this */ - } - } - up(&shared_codec_mutex); - } - card = bus->card; ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL); if (ac97 == NULL) @@ -2153,7 +2126,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) } } /* make sure the proper powerdown bits are cleared */ - if (ac97->scaps) { + if (ac97->scaps && ac97_is_audio(ac97)) { reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); if (ac97->scaps & AC97_SCAP_SURROUND_DAC) reg &= ~AC97_EA_PRJ; @@ -2167,13 +2140,6 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) return err; } *rac97 = ac97; - - if (bus->shared_type) { - down(&shared_codec_mutex); - shared_codec[bus->shared_type-1][ac97->num] = ac97; - up(&shared_codec_mutex); - } - return 0; } diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 241eacf1e652..cb1741102bbc 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1372,7 +1372,6 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) return err; pbus->clock = clock; - pbus->shared_type = AC97_SHARED_TYPE_ATIIXP; /* shared with modem driver */ chip->ac97_bus = pbus; codec_count = 0; diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c020c53a0cda..a88a6f372050 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1068,7 +1068,6 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) return err; pbus->clock = clock; - pbus->shared_type = AC97_SHARED_TYPE_ATIIXP; /* shared with audio driver */ chip->ac97_bus = pbus; codec_count = 0; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 1a96198a17ae..0d11cf7d569a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2022,7 +2022,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0) goto __err; pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; - pbus->shared_type = AC97_SHARED_TYPE_ICH; /* shared with modem driver */ if (ac97_clock >= 8000 && ac97_clock <= 48000) pbus->clock = ac97_clock; /* FIXME: my test board doesn't work well with VRA... */ diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 2ac1fec5059a..15364d27804d 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -855,7 +855,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) goto __err; pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; - pbus->shared_type = AC97_SHARED_TYPE_ICH; /* shared with audio driver */ if (ac97_clock >= 8000 && ac97_clock <= 48000) pbus->clock = ac97_clock; chip->ac97_bus = pbus; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3c0205b91e10..ecc4836ba8de 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1616,12 +1616,12 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov return err; chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; - chip->ac97_bus->shared_type = AC97_SHARED_TYPE_VIA; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_via82xx_mixer_free_ac97; ac97.pci = chip->pci; + ac97.scaps = AC97_SCAP_SKIP_MODEM; if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) return err; diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 034dc1c6262a..c3ab8fbf582c 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -879,7 +879,6 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip) return err; chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; - chip->ac97_bus->shared_type = AC97_SHARED_TYPE_VIA; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; -- cgit v1.2.3 From 7c22f1aaa23370bf9ba2dd3abbccbed70dced216 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:46:31 +0200 Subject: [ALSA] Remove snd_runtime_check() macro Remove snd_runtime_check() macro. This macro worsens the readability of codes. They should be either normal if() or removable asserts. Also, the assert displays stack-dump, instead of only the last caller pointer. Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 33 +++++------- include/sound/core.h | 34 ++++--------- sound/core/control.c | 18 +++---- sound/core/init.c | 5 +- sound/core/oss/mixer_oss.c | 59 +++++++++++++++------- sound/core/pcm.c | 3 +- sound/core/pcm_lib.c | 3 +- sound/core/pcm_native.c | 3 +- sound/core/seq/seq_midi.c | 2 - sound/core/timer.c | 3 +- sound/isa/cs423x/cs4236_lib.c | 5 +- sound/pci/ac97/ac97_codec.c | 1 - sound/pci/ac97/ac97_patch.c | 3 +- sound/pci/emu10k1/emufx.c | 34 +++++++++---- sound/pci/emu10k1/emupcm.c | 3 +- sound/pci/trident/trident_main.c | 3 +- sound/ppc/pmac.c | 16 +++--- 17 files changed, 126 insertions(+), 102 deletions(-) (limited to 'include') diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 24e85520890b..f3a2fdca9ad2 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -18,8 +18,8 @@ - March 6, 2005 - 0.3.4 + October 6, 2005 + 0.3.5 @@ -30,7 +30,7 @@ - Copyright (c) 2002-2004 Takashi Iwai tiwai@suse.de + Copyright (c) 2002-2005 Takashi Iwai tiwai@suse.de @@ -5998,32 +5998,23 @@ struct _snd_pcm_runtime { The first argument is the expression to evaluate, and the second argument is the action if it fails. When CONFIG_SND_DEBUG, is set, it will show an - error message such as BUG? (xxx) (called from - yyy). When no debug flag is set, this is - ignored. + error message such as BUG? (xxx) + together with stack trace. - - -
- <function>snd_runtime_check()</function> - This macro is quite similar with - snd_assert(). Unlike - snd_assert(), the expression is always - evaluated regardless of - CONFIG_SND_DEBUG. When - CONFIG_SND_DEBUG is set, the macro will - show a message like ERROR (xx) (called from - yyy). + When no debug flag is set, this macro is ignored.
<function>snd_BUG()</function> - It calls snd_assert(0,) -- that is, just - prints the error message at the point. It's useful to show that - a fatal error happens there. + It shows BUG? message and + stack trace as well as snd_assert at the point. + It's useful to show that a fatal error happens there. + + + When no debug flag is set, this macro is ignored.
diff --git a/include/sound/core.h b/include/sound/core.h index 6d971a4c4ca0..f0f54407fe5c 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -429,34 +429,24 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) * When CONFIG_SND_DEBUG is not set, the expression is executed but * not checked. */ -#define snd_assert(expr, args...) do {\ - if (unlikely(!(expr))) { \ - snd_printk(KERN_ERR "BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\ - args;\ - }\ +#define snd_assert(expr, args...) do { \ + if (unlikely(!(expr))) { \ + snd_printk(KERN_ERR "BUG? (%s)\n", __ASTRING__(expr)); \ + dump_stack(); \ + args; \ + } \ } while (0) -/** - * snd_runtime_check - run-time assertion macro - * @expr: expression - * @args...: the action - * - * This macro checks the expression in run-time and invokes the commands - * given in the rest arguments if the assertion is failed. - * Unlike snd_assert(), the action commands are executed even if - * CONFIG_SND_DEBUG is not set but without any error messages. - */ -#define snd_runtime_check(expr, args...) do {\ - if (unlikely(!(expr))) { \ - snd_printk(KERN_ERR "ERROR (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\ - args;\ - }\ + +#define snd_BUG() do { \ + snd_printk(KERN_ERR "BUG?\n"); \ + dump_stack(); \ } while (0) #else /* !CONFIG_SND_DEBUG */ #define snd_printd(fmt, args...) /* nothing */ #define snd_assert(expr, args...) (void)(expr) -#define snd_runtime_check(expr, args...) do { if (!(expr)) { args; } } while (0) +#define snd_BUG() /* nothing */ #endif /* CONFIG_SND_DEBUG */ @@ -473,8 +463,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #define snd_printdd(format, args...) /* nothing */ #endif -#define snd_BUG() snd_assert(0, ) - static inline void snd_timestamp_now(struct timespec *tstamp, int timespec) { diff --git a/sound/core/control.c b/sound/core/control.c index 736edf358e05..212c46a94376 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -144,7 +144,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id) snd_ctl_file_t *ctl; snd_kctl_event_t *ev; - snd_runtime_check(card != NULL && id != NULL, return); + snd_assert(card != NULL && id != NULL, return); read_lock(&card->ctl_files_rwlock); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) card->mixer_oss_change_count++; @@ -193,8 +193,8 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access) snd_kcontrol_t *kctl; unsigned int idx; - snd_runtime_check(control != NULL, return NULL); - snd_runtime_check(control->count > 0, return NULL); + snd_assert(control != NULL, return NULL); + snd_assert(control->count > 0, return NULL); kctl = kzalloc(sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL); if (kctl == NULL) return NULL; @@ -220,7 +220,7 @@ snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_ snd_kcontrol_t kctl; unsigned int access; - snd_runtime_check(ncontrol != NULL, return NULL); + snd_assert(ncontrol != NULL, return NULL); snd_assert(ncontrol->info != NULL, return NULL); memset(&kctl, 0, sizeof(kctl)); kctl.id.iface = ncontrol->iface; @@ -309,7 +309,7 @@ int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol) snd_ctl_elem_id_t id; unsigned int idx; - snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL); + snd_assert(card != NULL && kcontrol != NULL, return -EINVAL); snd_assert(kcontrol->info != NULL, return -EINVAL); id = kcontrol->id; down_write(&card->controls_rwsem); @@ -355,7 +355,7 @@ int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol) snd_ctl_elem_id_t id; unsigned int idx; - snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL); + snd_assert(card != NULL && kcontrol != NULL, return -EINVAL); list_del(&kcontrol->list); card->controls_count -= kcontrol->count; id = kcontrol->id; @@ -468,7 +468,7 @@ snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid) struct list_head *list; snd_kcontrol_t *kctl; - snd_runtime_check(card != NULL && numid != 0, return NULL); + snd_assert(card != NULL && numid != 0, return NULL); list_for_each(list, &card->controls) { kctl = snd_kcontrol(list); if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) @@ -494,7 +494,7 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id) struct list_head *list; snd_kcontrol_t *kctl; - snd_runtime_check(card != NULL && id != NULL, return NULL); + snd_assert(card != NULL && id != NULL, return NULL); if (id->numid != 0) return snd_ctl_find_numid(card, id->numid); list_for_each(list, &card->controls) { @@ -1215,7 +1215,7 @@ static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head struct list_head *list; snd_kctl_ioctl_t *p; - snd_runtime_check(fcn != NULL, return -EINVAL); + snd_assert(fcn != NULL, return -EINVAL); down_write(&snd_ioctl_rwsem); list_for_each(list, lists) { p = list_entry(list, snd_kctl_ioctl_t, list); diff --git a/sound/core/init.c b/sound/core/init.c index 41e224986f35..b98f7c6310c5 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -420,7 +420,7 @@ int snd_card_register(snd_card_t * card) int err; snd_info_entry_t *entry; - snd_runtime_check(card != NULL, return -EINVAL); + snd_assert(card != NULL, return -EINVAL); if ((err = snd_device_register_all(card)) < 0) return err; write_lock(&snd_card_rwlock); @@ -524,7 +524,8 @@ int __init snd_card_info_init(void) snd_info_entry_t *entry; entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); - snd_runtime_check(entry != NULL, return -ENOMEM); + if (! entry) + return -ENOMEM; entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_card_info_read; if (snd_info_register(entry) < 0) { diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 69e1059112d1..b2497cec2079 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -521,9 +521,13 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); - snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc); - snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; + if (kctl->get(kctl, uctl)) + goto __unalloc; + if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && + uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) + goto __unalloc; *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]); if (uinfo->count > 1) *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]); @@ -555,8 +559,10 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); - snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; + if (kctl->get(kctl, uctl)) + goto __unalloc; if (!uctl->value.integer.value[0]) { *left = 0; if (uinfo->count == 1) @@ -616,12 +622,16 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); - snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; + if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && + uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) + goto __unalloc; uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); if (uinfo->count > 1) uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); - snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc); + if ((res = kctl->put(kctl, uctl)) < 0) + goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unalloc: @@ -653,7 +663,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; if (uinfo->count > 1) { uctl->value.integer.value[0] = left > 0 ? 1 : 0; uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0; @@ -664,7 +675,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer, } else { uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; } - snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc); + if ((res = kctl->put(kctl, uctl)) < 0) + goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unalloc: @@ -776,9 +788,14 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); - snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock); - snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock); - snd_runtime_check(!(err = kctl->get(kctl, uctl)), goto __unlock); + if (! kctl) { + err = -ENOENT; + goto __unlock; + } + if ((err = kctl->info(kctl, uinfo)) < 0) + goto __unlock; + if ((err = kctl->get(kctl, uctl)) < 0) + goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; @@ -821,8 +838,12 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); - snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock); - snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock); + if (! kctl) { + err = -ENOENT; + goto __unlock; + } + if ((err = kctl->info(kctl, uinfo)) < 0) + goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; @@ -836,10 +857,11 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int break; slot = NULL; } - snd_runtime_check(slot != NULL, goto __unlock); + if (! slot) + goto __unlock; for (idx = 0; idx < uinfo->count; idx++) uctl->value.enumerated.item[idx] = slot->capture_item; - snd_runtime_check((err = kctl->put(kctl, uctl)) >= 0, ); + err = kctl->put(kctl, uctl); if (err > 0) snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); err = 0; @@ -1008,7 +1030,8 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os up_read(&mixer->card->controls_rwsem); if (slot.present != 0) { pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL); - snd_runtime_check(pslot != NULL, return -ENOMEM); + if (! pslot) + return -ENOMEM; *pslot = slot; pslot->signature = SNDRV_MIXER_OSS_SIGNATURE; pslot->assigned = ptr; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 1be470e942ef..184e74b75ba9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -273,7 +273,8 @@ static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buff snd_pcm_info_t *info; int err; - snd_runtime_check(substream, return); + if (! substream) + return; info = kmalloc(sizeof(*info), GFP_KERNEL); if (! info) { diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 0503980c23d9..dfc5f45f2748 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -156,9 +156,8 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *s #ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); - } else + } #endif - snd_runtime_check(pos < runtime->buffer_size, return 0); pos -= pos % runtime->min_align; return pos; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e97b2d162cc7..e6e2b70314c0 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2053,7 +2053,8 @@ static int snd_pcm_open(struct inode *inode, struct file *file) snd_pcm_file_t *pcm_file; wait_queue_t wait; - snd_runtime_check(device >= SNDRV_MINOR_PCM_PLAYBACK && device < SNDRV_MINOR_DEVICES, return -ENXIO); + if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES) + return -ENXIO; pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)]; if (pcm == NULL) { err = -ENODEV; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index b4674ae3bc30..f89f40f44876 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -449,11 +449,9 @@ snd_seq_midisynth_unregister_port(snd_seq_device_t *dev) client->ports_per_device[device] = 0; msynth = client->ports[device]; client->ports[device] = NULL; - snd_runtime_check(msynth != NULL || ports <= 0, goto __skip); for (p = 0; p < ports; p++) snd_seq_midisynth_delete(&msynth[p]); kfree(msynth); - __skip: client->num_ports--; if (client->num_ports <= 0) { snd_seq_delete_kernel_client(client->seq_client); diff --git a/sound/core/timer.c b/sound/core/timer.c index 22b104624084..128916c66085 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -879,7 +879,8 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t snd_timer_instance_t *ti, *ts; struct list_head *p, *n; - snd_runtime_check(timer->hw.flags & SNDRV_TIMER_HW_SLAVE, return); + if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) + return; snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && event <= SNDRV_TIMER_EVENT_MRESUME, return); spin_lock_irqsave(&timer->lock, flags); if (event == SNDRV_TIMER_EVENT_MSTART || diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 2128d4bdef41..1adb88d5f8f4 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -173,7 +173,10 @@ static unsigned char divisor_to_rate_register(unsigned int divisor) case 2117: return 6; case 2558: return 7; default: - snd_runtime_check(divisor >= 21 && divisor <= 192, return 192); + if (divisor < 21 || divisor > 192) { + snd_BUG(); + return 192; + } return divisor; } } diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 56549add80a8..bbc409ae7ee9 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1127,7 +1127,6 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97 { snd_kcontrol_new_t template; memcpy(&template, _template, sizeof(template)); - snd_runtime_check(!template.index, return NULL); template.index = ac97->num; return snd_ctl_new1(&template, ac97); } diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index b24beb32961e..de1c72ad2c6b 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1460,7 +1460,8 @@ int patch_ad1881(ac97_t * ac97) codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14)); codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13)); - snd_runtime_check(codecs[0] | codecs[1] | codecs[2], goto __end); + if (! (codecs[0] || codecs[1] || codecs[2])) + goto __end; for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.unchained[idx]) diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 20db3ac6cd61..177c4ad0f778 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -364,12 +364,18 @@ static int snd_emu10k1_gpr_ctl_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]); break; case EMU10K1_GPR_TRANSLATION_BASS: - snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error); + if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { + change = -EIO; + goto __error; + } for (j = 0; j < 5; j++) snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]); break; case EMU10K1_GPR_TRANSLATION_TREBLE: - snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error); + if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { + change = -EIO; + goto __error; + } for (j = 0; j < 5; j++) snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]); break; @@ -412,8 +418,6 @@ int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu, snd_emu10k1_fx8010_irq_t *irq; unsigned long flags; - snd_runtime_check(emu, return -EINVAL); - snd_runtime_check(handler, return -EINVAL); irq = kmalloc(sizeof(*irq), GFP_ATOMIC); if (irq == NULL) return -ENOMEM; @@ -442,7 +446,6 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, snd_emu10k1_fx8010_irq_t *tmp; unsigned long flags; - snd_runtime_check(irq, return -EINVAL); spin_lock_irqsave(&emu->fx8010.irq_lock, flags); if ((tmp = emu->fx8010.irq_handlers) == irq) { emu->fx8010.irq_handlers = tmp->next; @@ -717,9 +720,15 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode err = -EFAULT; goto __error; } - snd_runtime_check(gctl->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER || - gctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error); - snd_runtime_check(gctl->id.name[0] != '\0', err = -EINVAL; goto __error); + if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && + gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { + err = -EINVAL; + goto __error; + } + if (! gctl->id.name[0]) { + err = -EINVAL; + goto __error; + } ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id); memset(&knew, 0, sizeof(knew)); knew.iface = gctl->id.iface; @@ -783,7 +792,8 @@ static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { - snd_runtime_check(copy_from_user(&id, _id, sizeof(id)) == 0, return -EFAULT); + if (copy_from_user(&id, _id, sizeof(id))) + return -EFAULT; down_write(&card->controls_rwsem); ctl = snd_emu10k1_look_for_ctl(emu, &id); if (ctl) @@ -2075,14 +2085,16 @@ void snd_emu10k1_free_efx(emu10k1_t *emu) #if 0 // FIXME: who use them? int snd_emu10k1_fx8010_tone_control_activate(emu10k1_t *emu, int output) { - snd_runtime_check(output >= 0 && output < 6, return -EINVAL); + if (output < 0 || output >= 6) + return -EINVAL; snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1); return 0; } int snd_emu10k1_fx8010_tone_control_deactivate(emu10k1_t *emu, int output) { - snd_runtime_check(output >= 0 && output < 6, return -EINVAL); + if (output < 0 || output >= 6) + return -EINVAL; snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0); return 0; } diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 66ba27afe962..bf7490dae09b 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -965,7 +965,8 @@ static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, { snd_ctl_elem_id_t id; - snd_runtime_check(kctl != NULL, return); + if (! kctl) + return; if (activate) kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; else diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 777da9a7298b..dda62955b4fe 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -2893,7 +2893,8 @@ static void snd_trident_notify_pcm_change1(snd_card_t * card, snd_kcontrol_t *kc { snd_ctl_elem_id_t id; - snd_runtime_check(kctl != NULL, return); + if (! kctl) + return; if (activate) kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; else diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 392b2abd9f13..db2f1815fc30 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -220,7 +220,8 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr /* set up constraints */ astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - snd_runtime_check(astr, return -EINVAL); + if (! astr) + return -EINVAL; astr->cur_freqs = 1 << rate_index; astr->cur_formats = 1 << runtime->format; chip->rate_index = rate_index; @@ -467,7 +468,8 @@ static int snd_pmac_hw_rule_rate(snd_pcm_hw_params_t *params, pmac_stream_t *rec = snd_pmac_get_stream(chip, rule->deps[0]); int i, freq_table[8], num_freqs; - snd_runtime_check(rec, return -EINVAL); + if (! rec) + return -EINVAL; num_freqs = 0; for (i = chip->num_freqs - 1; i >= 0; i--) { if (rec->cur_freqs & (1 << i)) @@ -484,7 +486,8 @@ static int snd_pmac_hw_rule_format(snd_pcm_hw_params_t *params, pmac_t *chip = rule->private; pmac_stream_t *rec = snd_pmac_get_stream(chip, rule->deps[0]); - snd_runtime_check(rec, return -EINVAL); + if (! rec) + return -EINVAL; return snd_mask_refine_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), rec->cur_formats); } @@ -569,7 +572,8 @@ static int snd_pmac_pcm_close(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substrea snd_pmac_dma_stop(rec); astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - snd_runtime_check(astr, return -EINVAL); + if (! astr) + return -EINVAL; /* reset constraints */ astr->cur_freqs = chip->freqs_ok; @@ -1158,7 +1162,6 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) .dev_free = snd_pmac_dev_free, }; - snd_runtime_check(chip_return, return -EINVAL); *chip_return = NULL; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1382,7 +1385,8 @@ static int snd_pmac_sleep_notify(struct pmu_sleep_notifier *self, int when) pmac_t *chip; chip = sleeping_pmac; - snd_runtime_check(chip, return 0); + if (! chip) + return 0; switch (when) { case PBOOK_SLEEP_NOW: -- cgit v1.2.3 From 07799e756c76ecd52cb01a812ba48b7d8ac67633 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:49:49 +0200 Subject: [ALSA] Use getnstimeofday() Modules: Documentation,PCM Midlevel,Timer Midlevel,ALSA Core Use the standard getnstimeofday() function instead of ALSA's own one. Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 3 +-- include/sound/core.h | 23 ---------------------- include/sound/pcm.h | 3 +-- sound/core/pcm_lib.c | 2 +- sound/core/pcm_native.c | 14 ++++--------- sound/core/timer.c | 6 +++--- 6 files changed, 10 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index f3a2fdca9ad2..ab3dfe074fb1 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -2190,8 +2190,7 @@ struct _snd_pcm_runtime { unsigned int rate_den; /* -- SW params -- */ - int tstamp_timespec; /* use timeval (0) or timespec (1) */ - snd_pcm_tstamp_t tstamp_mode; /* mmap timestamp is updated */ + struct timespec tstamp_mode; /* mmap timestamp is updated */ unsigned int period_step; unsigned int sleep_min; /* min ticks to sleep */ snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ diff --git a/include/sound/core.h b/include/sound/core.h index f0f54407fe5c..fa8f4c9492cc 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -29,7 +29,6 @@ #include /* pm_message_t */ /* Typedef's */ -typedef struct timespec snd_timestamp_t; typedef struct sndrv_interval snd_interval_t; typedef enum sndrv_card_type snd_card_type; typedef struct sndrv_xferi snd_xferi_t; @@ -464,28 +463,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #endif -static inline void snd_timestamp_now(struct timespec *tstamp, int timespec) -{ - struct timeval val; - /* FIXME: use a linear time source */ - do_gettimeofday(&val); - tstamp->tv_sec = val.tv_sec; - tstamp->tv_nsec = val.tv_usec; - if (timespec) - tstamp->tv_nsec *= 1000L; -} - -static inline void snd_timestamp_zero(struct timespec *tstamp) -{ - tstamp->tv_sec = 0; - tstamp->tv_nsec = 0; -} - -static inline int snd_timestamp_null(struct timespec *tstamp) -{ - return tstamp->tv_sec == 0 && tstamp->tv_nsec == 0; -} - #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */ /* for easier backward-porting */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 2b23a5967071..acc4fa9d5abe 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -281,7 +281,7 @@ typedef struct { struct _snd_pcm_runtime { /* -- Status -- */ snd_pcm_substream_t *trigger_master; - snd_timestamp_t trigger_tstamp; /* trigger timestamp */ + struct timespec trigger_tstamp; /* trigger timestamp */ int overrange; snd_pcm_uframes_t avail_max; snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ @@ -306,7 +306,6 @@ struct _snd_pcm_runtime { unsigned int rate_den; /* -- SW params -- */ - int tstamp_timespec; /* use timeval (0) or timespec (1) */ snd_pcm_tstamp_t tstamp_mode; /* mmap timestamp is updated */ unsigned int period_step; unsigned int sleep_min; /* min ticks to sleep */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index dfc5f45f2748..3dbf9bf2ac16 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -152,7 +152,7 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *s if (pos == SNDRV_PCM_POS_XRUN) return pos; /* XRUN */ if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) - snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp, runtime->tstamp_timespec); + getnstimeofday((struct timespec *)&runtime->status->tstamp); #ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e6e2b70314c0..a1924f12d8fc 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -565,9 +565,9 @@ int snd_pcm_status(snd_pcm_substream_t *substream, if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) status->tstamp = runtime->status->tstamp; else - snd_timestamp_now(&status->tstamp, runtime->tstamp_timespec); + getnstimeofday(&status->tstamp); } else - snd_timestamp_now(&status->tstamp, runtime->tstamp_timespec); + getnstimeofday(&status->tstamp); status->appl_ptr = runtime->control->appl_ptr; status->hw_ptr = runtime->status->hw_ptr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -652,7 +652,7 @@ static void snd_pcm_trigger_tstamp(snd_pcm_substream_t *substream) if (runtime->trigger_master == NULL) return; if (runtime->trigger_master == substream) { - snd_timestamp_now(&runtime->trigger_tstamp, runtime->tstamp_timespec); + getnstimeofday(&runtime->trigger_tstamp); } else { snd_pcm_trigger_tstamp(runtime->trigger_master); runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; @@ -2446,14 +2446,8 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream, return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; case SNDRV_PCM_IOCTL_INFO: return snd_pcm_info_user(substream, arg); - case SNDRV_PCM_IOCTL_TSTAMP: - { - int xarg; - if (get_user(xarg, (int __user *)arg)) - return -EFAULT; - substream->runtime->tstamp_timespec = xarg ? 1 : 0; + case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */ return 0; - } case SNDRV_PCM_IOCTL_HW_REFINE: return snd_pcm_hw_refine_user(substream, arg); case SNDRV_PCM_IOCTL_HW_PARAMS: diff --git a/sound/core/timer.c b/sound/core/timer.c index 128916c66085..8ecec9134acd 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -385,7 +385,7 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e struct list_head *n; struct timespec tstamp; - snd_timestamp_now(&tstamp, 1); + getnstimeofday(&tstamp); snd_assert(event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE, return); if (event == SNDRV_TIMER_EVENT_START || event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); @@ -1156,14 +1156,14 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, struct timespec tstamp; int prev, append = 0; - snd_timestamp_zero(&tstamp); + memset(&tstamp, 0, sizeof(tstamp)); spin_lock(&tu->qlock); if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION)|(1 << SNDRV_TIMER_EVENT_TICK))) == 0) { spin_unlock(&tu->qlock); return; } if (tu->last_resolution != resolution || ticks > 0) - snd_timestamp_now(&tstamp, 1); + getnstimeofday(&tstamp); if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { r1.event = SNDRV_TIMER_EVENT_RESOLUTION; r1.tstamp = tstamp; -- cgit v1.2.3 From 93f2e37840a9a7c3693ca6961fe6ad46b250f3b9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:51:55 +0200 Subject: [ALSA] Make snd_task_name() module local Modules: ALSA Core,ALSA<-OSS emulation Remove a global function snd_task_name(), and move it local to snd-pcm-oss module. Signed-off-by: Takashi Iwai --- include/sound/core.h | 1 - sound/core/misc.c | 11 ----------- sound/core/oss/pcm_oss.c | 11 +++++++++++ sound/core/sound.c | 1 - 4 files changed, 11 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/sound/core.h b/include/sound/core.h index fa8f4c9492cc..af314205635d 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -373,7 +373,6 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); /* misc.c */ -int snd_task_name(struct task_struct *task, char *name, size_t size); #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 3, 4))); diff --git a/sound/core/misc.c b/sound/core/misc.c index 1a81fe4df218..11a7675b719b 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -25,17 +25,6 @@ #include #include -int snd_task_name(struct task_struct *task, char *name, size_t size) -{ - unsigned int idx; - - snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); - for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) - name[idx] = task->comm[idx]; - name[idx] = '\0'; - return 0; -} - #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 842c28b2ed55..c57f702d31a7 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1821,6 +1821,17 @@ static int snd_pcm_oss_open_file(struct file *file, } +static int snd_task_name(struct task_struct *task, char *name, size_t size) +{ + unsigned int idx; + + snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); + for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) + name[idx] = task->comm[idx]; + name[idx] = '\0'; + return 0; +} + static int snd_pcm_oss_open(struct inode *inode, struct file *file) { int minor = iminor(inode); diff --git a/sound/core/sound.c b/sound/core/sound.c index b57519a3e3d9..bc8ad0017984 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -487,7 +487,6 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); /* misc.c */ -EXPORT_SYMBOL(snd_task_name); #ifdef CONFIG_SND_VERBOSE_PRINTK EXPORT_SYMBOL(snd_verbose_printk); #endif -- cgit v1.2.3 From b1d5776d865951c213a1caaab5d8bf5de7615dbd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:56:31 +0200 Subject: [ALSA] Remove vmalloc wrapper, kfree_nocheck() - Remove vmalloc wrapper - Add release_and_free_resource() to remove kfree_nocheck() from each driver and simplify the code Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 17 +------ include/sound/core.h | 9 +--- include/sound/driver.h | 4 -- sound/core/memory.c | 53 ---------------------- sound/core/misc.c | 9 ++++ sound/core/sound.c | 5 +- sound/core/wrappers.c | 10 ---- sound/drivers/mpu401/mpu401_uart.c | 5 +- sound/drivers/mtpav.c | 5 +- sound/drivers/opl3/opl3_lib.c | 10 +--- sound/drivers/opl4/opl4_lib.c | 10 +--- sound/drivers/serial-u16550.c | 5 +- sound/drivers/vx/vx_pcm.c | 4 +- sound/isa/ad1816a/ad1816a_lib.c | 5 +- sound/isa/ad1848/ad1848_lib.c | 5 +- sound/isa/cs423x/cs4231_lib.c | 10 +--- sound/isa/cs423x/cs4236.c | 8 +--- sound/isa/es1688/es1688_lib.c | 3 +- sound/isa/es18xx.c | 15 ++---- sound/isa/gus/gus_main.c | 10 +--- sound/isa/gus/interwave.c | 5 +- sound/isa/opl3sa2.c | 5 +- sound/isa/opti9xx/opti92x-ad1848.c | 25 +++------- sound/isa/sb/emu8000.c | 15 ++---- sound/isa/sb/sb16.c | 5 +- sound/isa/sb/sb8.c | 5 +- sound/isa/sb/sb_common.c | 6 +-- sound/isa/sscape.c | 6 +-- sound/isa/wavefront/wavefront.c | 5 +- sound/mips/au1x00.c | 3 +- sound/pci/als4000.c | 6 +-- sound/pci/azt3328.c | 6 +-- sound/pci/ca0106/ca0106_main.c | 6 +-- sound/pci/cmipci.c | 6 +-- sound/pci/cs46xx/cs46xx_lib.c | 5 +- sound/pci/emu10k1/emu10k1x.c | 6 +-- sound/pci/es1968.c | 6 +-- sound/pci/nm256/nm256.c | 10 +--- sound/pci/sonicvibes.c | 10 +--- sound/pci/via82xx.c | 11 ++--- sound/pci/ymfpci/ymfpci.c | 16 ++----- sound/pci/ymfpci/ymfpci_main.c | 15 ++---- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 6 +-- sound/usb/usbaudio.c | 6 +-- 44 files changed, 86 insertions(+), 311 deletions(-) (limited to 'include') diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index ab3dfe074fb1..05ae29ac898c 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -1433,25 +1433,10 @@ res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); ]]> - - As you can see, the resource pointer is also to be freed - via kfree_nocheck() after - release_resource() is called. You - cannot use kfree() here, because on ALSA, - kfree() may be a wrapper to its own - allocator with the memory debugging. Since the resource pointer - is allocated externally outside the ALSA, it must be released - via the native - kfree(). - kfree_nocheck() is used for that; it calls - the native kfree() without wrapper.
diff --git a/include/sound/core.h b/include/sound/core.h index af314205635d..0a14885fb1d7 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -293,19 +293,13 @@ void *snd_hidden_kmalloc(size_t size, gfp_t flags); void *snd_hidden_kzalloc(size_t size, gfp_t flags); void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); void snd_hidden_kfree(const void *obj); -void *snd_hidden_vmalloc(unsigned long size); -void snd_hidden_vfree(void *obj); char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) #define kfree(obj) snd_hidden_kfree(obj) -#define vmalloc(size) snd_hidden_vmalloc(size) -#define vfree(obj) snd_hidden_vfree(obj) #define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags) -#define vmalloc_nocheck(size) snd_wrapper_vmalloc(size) #define kfree_nocheck(obj) snd_wrapper_kfree(obj) -#define vfree_nocheck(obj) snd_wrapper_vfree(obj) #define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) #else #define snd_memory_init() /*NOP*/ @@ -313,9 +307,7 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define snd_memory_info_init() /*NOP*/ #define snd_memory_info_done() /*NOP*/ #define kmalloc_nocheck(size, flags) kmalloc(size, flags) -#define vmalloc_nocheck(size) vmalloc(size) #define kfree_nocheck(obj) kfree(obj) -#define vfree_nocheck(obj) vfree(obj) #endif int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); @@ -372,6 +364,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); #endif /* misc.c */ +void release_and_free_resource(struct resource *res); #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) diff --git a/include/sound/driver.h b/include/sound/driver.h index 1ec2fae050a6..7973e0c05ae3 100644 --- a/include/sound/driver.h +++ b/include/sound/driver.h @@ -55,10 +55,6 @@ void *snd_wrapper_kmalloc(size_t, gfp_t); #undef kmalloc void snd_wrapper_kfree(const void *); #undef kfree -void *snd_wrapper_vmalloc(size_t); -#undef vmalloc -void snd_wrapper_vfree(void *); -#undef vfree #endif #endif /* __SOUND_DRIVER_H */ diff --git a/sound/core/memory.c b/sound/core/memory.c index 7d8e2eebba51..b99343616f81 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -47,19 +47,14 @@ struct snd_alloc_track { #define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data) static long snd_alloc_kmalloc; -static long snd_alloc_vmalloc; static LIST_HEAD(snd_alloc_kmalloc_list); -static LIST_HEAD(snd_alloc_vmalloc_list); static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); -static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock); #define KMALLOC_MAGIC 0x87654321 -#define VMALLOC_MAGIC 0x87654320 static snd_info_entry_t *snd_memory_info_entry; void __init snd_memory_init(void) { snd_alloc_kmalloc = 0; - snd_alloc_vmalloc = 0; } void snd_memory_done(void) @@ -69,8 +64,6 @@ void snd_memory_done(void) if (snd_alloc_kmalloc > 0) snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc); - if (snd_alloc_vmalloc > 0) - snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc); list_for_each_prev(head, &snd_alloc_kmalloc_list) { t = list_entry(head, struct snd_alloc_track, list); if (t->magic != KMALLOC_MAGIC) { @@ -79,14 +72,6 @@ void snd_memory_done(void) } snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); } - list_for_each_prev(head, &snd_alloc_vmalloc_list) { - t = list_entry(head, struct snd_alloc_track, list); - if (t->magic != VMALLOC_MAGIC) { - snd_printk(KERN_ERR "Corrupted vmalloc\n"); - break; - } - snd_printk(KERN_ERR "vmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); - } } static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) @@ -153,43 +138,6 @@ void snd_hidden_kfree(const void *obj) snd_wrapper_kfree(obj); } -void *snd_hidden_vmalloc(unsigned long size) -{ - void *ptr; - ptr = snd_wrapper_vmalloc(size + sizeof(struct snd_alloc_track)); - if (ptr) { - struct snd_alloc_track *t = (struct snd_alloc_track *)ptr; - t->magic = VMALLOC_MAGIC; - t->caller = __builtin_return_address(0); - spin_lock(&snd_alloc_vmalloc_lock); - list_add_tail(&t->list, &snd_alloc_vmalloc_list); - spin_unlock(&snd_alloc_vmalloc_lock); - t->size = size; - snd_alloc_vmalloc += size; - ptr = t->data; - } - return ptr; -} - -void snd_hidden_vfree(void *obj) -{ - struct snd_alloc_track *t; - if (obj == NULL) - return; - t = snd_alloc_track_entry(obj); - if (t->magic != VMALLOC_MAGIC) { - snd_printk(KERN_ERR "bad vfree (called from %p)\n", __builtin_return_address(0)); - return; - } - spin_lock(&snd_alloc_vmalloc_lock); - list_del(&t->list); - spin_unlock(&snd_alloc_vmalloc_lock); - t->magic = 0; - snd_alloc_vmalloc -= t->size; - obj = t; - snd_wrapper_vfree(obj); -} - char *snd_hidden_kstrdup(const char *s, gfp_t flags) { int len; @@ -207,7 +155,6 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags) static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); - snd_iprintf(buffer, "vmalloc: %li bytes\n", snd_alloc_vmalloc); } int __init snd_memory_info_init(void) diff --git a/sound/core/misc.c b/sound/core/misc.c index 11a7675b719b..3eddfdede9f3 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -23,8 +23,17 @@ #include #include #include +#include #include +void release_and_free_resource(struct resource *res) +{ + if (res) { + release_resource(res); + kfree_nocheck(res); + } +} + #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { diff --git a/sound/core/sound.c b/sound/core/sound.c index bc8ad0017984..e94eebd8ad6f 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -407,8 +407,6 @@ EXPORT_SYMBOL(snd_unregister_oss_device); EXPORT_SYMBOL(snd_hidden_kmalloc); EXPORT_SYMBOL(snd_hidden_kcalloc); EXPORT_SYMBOL(snd_hidden_kfree); -EXPORT_SYMBOL(snd_hidden_vmalloc); -EXPORT_SYMBOL(snd_hidden_vfree); EXPORT_SYMBOL(snd_hidden_kstrdup); #endif EXPORT_SYMBOL(copy_to_user_fromio); @@ -487,6 +485,7 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); /* misc.c */ +EXPORT_SYMBOL(release_and_free_resource); #ifdef CONFIG_SND_VERBOSE_PRINTK EXPORT_SYMBOL(snd_verbose_printk); #endif @@ -497,6 +496,4 @@ EXPORT_SYMBOL(snd_verbose_printd); #ifdef CONFIG_SND_DEBUG_MEMORY EXPORT_SYMBOL(snd_wrapper_kmalloc); EXPORT_SYMBOL(snd_wrapper_kfree); -EXPORT_SYMBOL(snd_wrapper_vmalloc); -EXPORT_SYMBOL(snd_wrapper_vfree); #endif diff --git a/sound/core/wrappers.c b/sound/core/wrappers.c index 296b716f1376..19e899089cb3 100644 --- a/sound/core/wrappers.c +++ b/sound/core/wrappers.c @@ -36,15 +36,5 @@ void snd_wrapper_kfree(const void *obj) { kfree(obj); } - -void *snd_wrapper_vmalloc(unsigned long size) -{ - return vmalloc(size); -} - -void snd_wrapper_vfree(void *obj) -{ - vfree(obj); -} #endif diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index fe3f921ffbe3..bdeb2c00dac5 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -423,10 +423,7 @@ static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi) mpu401_t *mpu = rmidi->private_data; if (mpu->irq_flags && mpu->irq >= 0) free_irq(mpu->irq, (void *) mpu); - if (mpu->res) { - release_resource(mpu->res); - kfree_nocheck(mpu->res); - } + release_and_free_resource(mpu->res); kfree(mpu); } diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 3a25c89d2983..e9d52c668edc 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -717,10 +717,7 @@ static void free_mtpav(mtpav_t * crd) spin_unlock_irqrestore(&crd->spinlock, flags); if (crd->irq >= 0) free_irq(crd->irq, (void *)crd); - if (crd->res_port) { - release_resource(crd->res_port); - kfree_nocheck(crd->res_port); - } + release_and_free_resource(crd->res_port); kfree(crd); } diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 1f84d78260de..06246503083c 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -325,14 +325,8 @@ static int snd_opl3_free(opl3_t *opl3) snd_assert(opl3 != NULL, return -ENXIO); if (opl3->private_free) opl3->private_free(opl3); - if (opl3->res_l_port) { - release_resource(opl3->res_l_port); - kfree_nocheck(opl3->res_l_port); - } - if (opl3->res_r_port) { - release_resource(opl3->res_r_port); - kfree_nocheck(opl3->res_r_port); - } + release_and_free_resource(opl3->res_l_port); + release_and_free_resource(opl3->res_r_port); kfree(opl3); return 0; } diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 380c2c704c54..4ae5dd8f011e 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -169,14 +169,8 @@ static void snd_opl4_free(opl4_t *opl4) #ifdef CONFIG_PROC_FS snd_opl4_free_proc(opl4); #endif - if (opl4->res_fm_port) { - release_resource(opl4->res_fm_port); - kfree_nocheck(opl4->res_fm_port); - } - if (opl4->res_pcm_port) { - release_resource(opl4->res_pcm_port); - kfree_nocheck(opl4->res_pcm_port); - } + release_and_free_resource(opl4->res_fm_port); + release_and_free_resource(opl4->res_pcm_port); kfree(opl4); } diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 416172ea1f47..1ed58df42671 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -749,10 +749,7 @@ static int snd_uart16550_free(snd_uart16550_t *uart) { if (uart->irq >= 0) free_irq(uart->irq, (void *)uart); - if (uart->res_base) { - release_resource(uart->res_base); - kfree_nocheck(uart->res_base); - } + release_and_free_resource(uart->res_base); kfree(uart); return 0; }; diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index c2312d912fc7..2b46758fe86f 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -79,7 +79,7 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) /* already allocated */ if (runtime->dma_bytes >= size) return 0; /* already enough large */ - vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */ + vfree(runtime->dma_area); } runtime->dma_area = vmalloc_32(size); if (! runtime->dma_area) @@ -98,7 +98,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) { snd_pcm_runtime_t *runtime = subs->runtime; if (runtime->dma_area) { - vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */ + vfree(runtime->dma_area); runtime->dma_area = NULL; } return 0; diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 27a9dcfbba00..7ae02396cae2 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -542,10 +542,7 @@ static int snd_ad1816a_probe(ad1816a_t *chip) static int snd_ad1816a_free(ad1816a_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma1 >= 0) { diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 303861cd03cd..0c2924dfefaf 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -846,10 +846,7 @@ static int snd_ad1848_capture_close(snd_pcm_substream_t * substream) static int snd_ad1848_free(ad1848_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma >= 0) { diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index 32318258cd8e..4af769030beb 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c @@ -1417,14 +1417,8 @@ static int snd_cs4231_pm_resume(snd_card_t *card) static int snd_cs4231_free(cs4231_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } - if (chip->res_cport) { - release_resource(chip->res_cport); - kfree_nocheck(chip->res_cport); - } + release_and_free_resource(chip->res_port); + release_and_free_resource(chip->res_cport); if (chip->irq >= 0) { disable_irq(chip->irq); if (!(chip->hwshare & CS4231_HWSHARE_IRQ)) diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index d28315dc72f7..d60a55e6a0b1 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -379,12 +379,8 @@ static void snd_card_cs4236_free(snd_card_t *card) { struct snd_card_cs4236 *acard = (struct snd_card_cs4236 *)card->private_data; - if (acard) { - if (acard->res_sb_port) { - release_resource(acard->res_sb_port); - kfree_nocheck(acard->res_sb_port); - } - } + if (acard) + release_and_free_resource(acard->res_sb_port); } #ifdef CONFIG_PNP diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index aac898765c02..2edc9c9f0445 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -606,8 +606,7 @@ static int snd_es1688_free(es1688_t *chip) { if (chip->res_port) { snd_es1688_init(chip, 0); - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); + release_and_free_resource(chip->res_port); } if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index d0ea19f42703..f0f8505cd1a5 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1640,18 +1640,9 @@ static int snd_es18xx_resume(snd_card_t *card) static int snd_es18xx_free(es18xx_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } - if (chip->res_ctrl_port) { - release_resource(chip->res_ctrl_port); - kfree_nocheck(chip->res_ctrl_port); - } - if (chip->res_mpu_port) { - release_resource(chip->res_mpu_port); - kfree_nocheck(chip->res_mpu_port); - } + release_and_free_resource(chip->res_port); + release_and_free_resource(chip->res_ctrl_port); + release_and_free_resource(chip->res_mpu_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma1 >= 0) { diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 8f2872f8e8f6..5fd374f052ec 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -113,14 +113,8 @@ static int snd_gus_free(snd_gus_card_t *gus) snd_gf1_stop(gus); snd_gus_init_dma_irq(gus, 0); __hw_end: - if (gus->gf1.res_port1) { - release_resource(gus->gf1.res_port1); - kfree_nocheck(gus->gf1.res_port1); - } - if (gus->gf1.res_port2) { - release_resource(gus->gf1.res_port2); - kfree_nocheck(gus->gf1.res_port2); - } + release_and_free_resource(gus->gf1.res_port1); + release_and_free_resource(gus->gf1.res_port2); if (gus->gf1.irq >= 0) free_irq(gus->gf1.irq, (void *) gus); if (gus->gf1.dma1 >= 0) { diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 358cba9d738f..b101ab0a0dbf 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -638,10 +638,7 @@ static void snd_interwave_free(snd_card_t *card) if (iwcard == NULL) return; #ifdef SNDRV_STB - if (iwcard->i2c_res) { - release_resource(iwcard->i2c_res); - kfree_nocheck(iwcard->i2c_res); - } + release_and_free_resource(iwcard->i2c_res); #endif if (iwcard->irq >= 0) free_irq(iwcard->irq, (void *)iwcard); diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 4ba268f251e3..47cabda792b6 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -656,10 +656,7 @@ static int snd_opl3sa2_free(opl3sa2_t *chip) { if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); kfree(chip); return 0; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 73573cb1db6a..b94339f8306f 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -299,10 +299,8 @@ static char * snd_opti9xx_names[] = { static long snd_legacy_find_free_ioport(long *port_table, long size) { while (*port_table != -1) { - struct resource *res; - if ((res = request_region(*port_table, size, "ALSA test")) != NULL) { - release_resource(res); - kfree_nocheck(res); + if (request_region(*port_table, size, "ALSA test")) { + release_region(*port_table, size); return *port_table; } port_table++; @@ -1227,10 +1225,7 @@ static int snd_opti93x_probe(opti93x_t *chip) static int snd_opti93x_free(opti93x_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); if (chip->dma1 >= 0) { disable_dma(chip->dma1); free_dma(chip->dma1); @@ -1656,8 +1651,7 @@ static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip) if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) return 1; - release_resource(chip->res_mc_base); - kfree_nocheck(chip->res_mc_base); + release_and_free_resource(chip->res_mc_base); chip->res_mc_base = NULL; } @@ -1683,8 +1677,7 @@ static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip) if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value) return 1; - release_resource(chip->res_mc_base); - kfree_nocheck(chip->res_mc_base); + release_and_free_resource(chip->res_mc_base); chip->res_mc_base = NULL; } #endif /* OPTi93X */ @@ -1886,12 +1879,8 @@ static void snd_card_opti9xx_free(snd_card_t *card) { opti9xx_t *chip = (opti9xx_t *)card->private_data; - if (chip) { - if (chip->res_mc_base) { - release_resource(chip->res_mc_base); - kfree_nocheck(chip->res_mc_base); - } - } + if (chip) + release_and_free_resource(chip->res_mc_base); } static int snd_card_opti9xx_probe(struct pnp_card_link *pcard, diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 5375705c054b..95540f133199 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -1054,18 +1054,9 @@ __error: */ static int snd_emu8000_free(emu8000_t *hw) { - if (hw->res_port1) { - release_resource(hw->res_port1); - kfree_nocheck(hw->res_port1); - } - if (hw->res_port2) { - release_resource(hw->res_port2); - kfree_nocheck(hw->res_port2); - } - if (hw->res_port3) { - release_resource(hw->res_port3); - kfree_nocheck(hw->res_port3); - } + release_and_free_resource(hw->res_port1); + release_and_free_resource(hw->res_port2); + release_and_free_resource(hw->res_port3); kfree(hw); return 0; } diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 7888783d68f5..c2fa451bc8f0 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -345,10 +345,7 @@ static void snd_sb16_free(snd_card_t *card) if (acard == NULL) return; - if (acard->fm_res) { - release_resource(acard->fm_res); - kfree_nocheck(acard->fm_res); - } + release_and_free_resource(acard->fm_res); } #ifdef CONFIG_PNP diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index c41ac25e85ca..0bc0a3afdabc 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -78,10 +78,7 @@ static void snd_sb8_free(snd_card_t *card) if (acard == NULL) return; - if (acard->fm_res) { - release_resource(acard->fm_res); - kfree_nocheck(acard->fm_res); - } + release_and_free_resource(acard->fm_res); } static int __init snd_sb8_probe(int dev) diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index f0f205ae425f..46b9480669f9 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -178,10 +178,8 @@ static int snd_sbdsp_probe(sb_t * chip) static int snd_sbdsp_free(sb_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + if (chip->res_port) + release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); #ifdef CONFIG_ISA diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 9f6b58c79209..1036876146c4 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -338,8 +338,7 @@ static inline void activate_ad1845_unsafe(unsigned io_base) static void soundscape_free(snd_card_t * c) { register struct soundscape *sscape = get_card_soundscape(c); - release_resource(sscape->io_res); - kfree_nocheck(sscape->io_res); + release_and_free_resource(sscape->io_res); free_dma(sscape->chip->dma1); } @@ -1288,8 +1287,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca free_dma(params->dma1); _release_region: - release_resource(io_res); - kfree_nocheck(io_res); + release_and_free_resource(io_res); return err; } diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 0a572e0a47e6..1818f1013c3f 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -379,10 +379,7 @@ snd_wavefront_free(snd_card_t *card) snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data; if (acard) { - if (acard->wavefront.res_base != NULL) { - release_resource(acard->wavefront.res_base); - kfree_nocheck(acard->wavefront.res_base); - } + release_and_free_resource(acard->wavefront.res_base); if (acard->wavefront.irq > 0) free_irq(acard->wavefront.irq, (void *)acard); } diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 3f9684f1d1d2..b7af85f5bfb4 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -606,8 +606,7 @@ snd_au1000_free(snd_card_t *card) /* put internal AC97 block into reset */ au1000->ac97_ioport->cntrl = AC97C_RS; au1000->ac97_ioport = NULL; - release_resource(au1000->ac97_res_port); - kfree_nocheck(au1000->ac97_res_port); + release_and_free_resource(au1000->ac97_res_port); } if (au1000->stream[PLAYBACK]->dma >= 0) diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 196ec1c61bb4..8a32cd92f62a 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -594,8 +594,7 @@ static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int acard->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "als4000: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -622,8 +621,7 @@ static void snd_als4000_free_gameport(snd_card_als4000_t *acard) acard->gameport = NULL; snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */ - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index d5261bdec583..dc638f395c02 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1238,8 +1238,7 @@ static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev) chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -1267,8 +1266,7 @@ static void snd_azf3328_free_joystick(azf3328_t *chip) /* disable gameport */ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index ba07960921d8..0d9d8923fbbb 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -969,10 +969,8 @@ static int snd_ca0106_free(ca0106_t *chip) #endif // release the i/o port - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); + // release the irq if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 316afb78488d..db093bca2cd0 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2683,8 +2683,7 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev) cm->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } gameport_set_name(gp, "C-Media Gameport"); @@ -2709,8 +2708,7 @@ static void snd_cmipci_free_gameport(cmipci_t *cm) cm->gameport = NULL; snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 6e3855b8b33d..147836f09dcf 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2906,10 +2906,7 @@ static int snd_cs46xx_free(cs46xx_t *chip) snd_cs46xx_region_t *region = &chip->region.idx[idx]; if (region->remap_addr) iounmap(region->remap_addr); - if (region->resource) { - release_resource(region->resource); - kfree_nocheck(region->resource); - } + release_and_free_resource(region->resource); } if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index ad15755a63c3..cbb689474e7d 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -759,10 +759,8 @@ static int snd_emu10k1x_free(emu10k1x_t *chip) outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); // release the i/o port - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); + // release the irq if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index ecdcada90ca2..1bf094b67469 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2461,8 +2461,7 @@ static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev) chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "es1968: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -2488,8 +2487,7 @@ static void snd_es1968_free_gameport(es1968_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 5c55a3b1d121..ebfa38b51128 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1347,14 +1347,8 @@ static int snd_nm256_free(nm256_t *chip) iounmap(chip->cport); if (chip->buffer) iounmap(chip->buffer); - if (chip->res_cport) { - release_resource(chip->res_cport); - kfree_nocheck(chip->res_cport); - } - if (chip->res_buffer) { - release_resource(chip->res_buffer); - kfree_nocheck(chip->res_buffer); - } + release_and_free_resource(chip->res_cport); + release_and_free_resource(chip->res_buffer); if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 1f6c2bfd43fd..4f64814dfef0 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1205,14 +1205,8 @@ static int snd_sonicvibes_free(sonicvibes_t *sonic) pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port); if (sonic->irq >= 0) free_irq(sonic->irq, (void *)sonic); - if (sonic->res_dmaa) { - release_resource(sonic->res_dmaa); - kfree_nocheck(sonic->res_dmaa); - } - if (sonic->res_dmac) { - release_resource(sonic->res_dmac); - kfree_nocheck(sonic->res_dmac); - } + release_and_free_resource(sonic->res_dmaa); + release_and_free_resource(sonic->res_dmac); pci_release_regions(sonic->pci); pci_disable_device(sonic->pci); kfree(sonic); diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b2779fb7d1a9..b0302c369c3d 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1655,8 +1655,7 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char * chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -1682,8 +1681,7 @@ static void snd_via686_free_gameport(via82xx_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else @@ -2023,10 +2021,7 @@ static int snd_via82xx_free(via82xx_t *chip) __end_hw: if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - if (chip->mpu_res) { - release_resource(chip->mpu_res); - kfree_nocheck(chip->mpu_res); - } + release_and_free_resource(chip->mpu_res); pci_release_regions(chip->pci); if (chip->chip_type == TYPE_VIA686) { diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 2e69abe51aa9..e50d744ae706 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -130,8 +130,7 @@ static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev, chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -161,8 +160,7 @@ void snd_ymfpci_free_gameport(ymfpci_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else @@ -267,14 +265,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, old_legacy_ctrl, &chip)) < 0) { snd_card_free(card); - if (mpu_res) { - release_resource(mpu_res); - kfree_nocheck(mpu_res); - } - if (fm_res) { - release_resource(fm_res); - kfree_nocheck(fm_res); - } + release_and_free_resource(mpu_res); + release_and_free_resource(fm_res); return err; } chip->fm_res = fm_res; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 2e671ee438c6..c0aaade772d4 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -2151,14 +2151,8 @@ static int snd_ymfpci_free(ymfpci_t *chip) #ifdef CONFIG_PM vfree(chip->saved_regs); #endif - if (chip->mpu_res) { - release_resource(chip->mpu_res); - kfree_nocheck(chip->mpu_res); - } - if (chip->fm_res) { - release_resource(chip->fm_res); - kfree_nocheck(chip->fm_res); - } + release_and_free_resource(chip->mpu_res); + release_and_free_resource(chip->fm_res); snd_ymfpci_free_gameport(chip); if (chip->reg_area_virt) iounmap(chip->reg_area_virt); @@ -2167,10 +2161,7 @@ static int snd_ymfpci_free(ymfpci_t *chip) if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - if (chip->res_reg_area) { - release_resource(chip->res_reg_area); - kfree_nocheck(chip->res_reg_area); - } + release_and_free_resource(chip->res_reg_area); pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 0a954dc11b73..20b86d8df7a3 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -50,9 +50,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) if (runtime->dma_area) { if (runtime->dma_bytes >= size) return 0; /* already enough large */ - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_nocheck(size); + runtime->dma_area = vmalloc_32(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; @@ -67,7 +67,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) { snd_pcm_runtime_t *runtime = subs->runtime; if (runtime->dma_area) { - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); runtime->dma_area = NULL; } return 0; diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 5429b169877a..4589c637a25e 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -692,9 +692,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) if (runtime->dma_area) { if (runtime->dma_bytes >= size) return 0; /* already large enough */ - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_nocheck(size); + runtime->dma_area = vmalloc(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; @@ -706,7 +706,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) { snd_pcm_runtime_t *runtime = subs->runtime; if (runtime->dma_area) { - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); runtime->dma_area = NULL; } return 0; -- cgit v1.2.3 From e38e0cfa48ac38f4fe24453d2523852467c95b21 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:59:52 +0200 Subject: [ALSA] Remove kmalloc wrappers Modules: ALSA Core Remove kmalloc wrappers. Signed-off-by: Takashi Iwai --- include/sound/core.h | 25 -------- include/sound/driver.h | 13 ---- sound/core/Kconfig | 6 -- sound/core/Makefile | 3 +- sound/core/info.c | 2 - sound/core/memory.c | 163 +------------------------------------------------ sound/core/misc.c | 2 +- sound/core/sound.c | 14 ----- 8 files changed, 4 insertions(+), 224 deletions(-) (limited to 'include') diff --git a/include/sound/core.h b/include/sound/core.h index 0a14885fb1d7..ed56a356ab7d 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -284,31 +284,6 @@ int snd_oss_init_module(void); /* memory.c */ -#ifdef CONFIG_SND_DEBUG_MEMORY -void snd_memory_init(void); -void snd_memory_done(void); -int snd_memory_info_init(void); -int snd_memory_info_done(void); -void *snd_hidden_kmalloc(size_t size, gfp_t flags); -void *snd_hidden_kzalloc(size_t size, gfp_t flags); -void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); -void snd_hidden_kfree(const void *obj); -char *snd_hidden_kstrdup(const char *s, gfp_t flags); -#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) -#define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) -#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) -#define kfree(obj) snd_hidden_kfree(obj) -#define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags) -#define kfree_nocheck(obj) snd_wrapper_kfree(obj) -#define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) -#else -#define snd_memory_init() /*NOP*/ -#define snd_memory_done() /*NOP*/ -#define snd_memory_info_init() /*NOP*/ -#define snd_memory_info_done() /*NOP*/ -#define kmalloc_nocheck(size, flags) kmalloc(size, flags) -#define kfree_nocheck(obj) kfree(obj) -#endif int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); diff --git a/include/sound/driver.h b/include/sound/driver.h index 7973e0c05ae3..3f0416ac24d9 100644 --- a/include/sound/driver.h +++ b/include/sound/driver.h @@ -44,17 +44,4 @@ #include -/* - * ========================================================================== - */ - -#ifdef CONFIG_SND_DEBUG_MEMORY -#include -#include -void *snd_wrapper_kmalloc(size_t, gfp_t); -#undef kmalloc -void snd_wrapper_kfree(const void *); -#undef kfree -#endif - #endif /* __SOUND_DRIVER_H */ diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 48cf45cfd0b7..82718836f937 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -127,12 +127,6 @@ config SND_DEBUG help Say Y here to enable ALSA debug code. -config SND_DEBUG_MEMORY - bool "Debug memory" - depends on SND_DEBUG - help - Say Y here to enable debugging of memory allocations. - config SND_DEBUG_DETECT bool "Debug detection" depends on SND_DEBUG diff --git a/sound/core/Makefile b/sound/core/Makefile index 969d75528bde..5a01c76d02e8 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -3,8 +3,7 @@ # Copyright (c) 1999,2001 by Jaroslav Kysela # -snd-objs := sound.o init.o memory.o info.o control.o misc.o \ - device.o wrappers.o +snd-objs := sound.o init.o memory.o info.o control.o misc.o device.o ifeq ($(CONFIG_ISA_DMA_API),y) snd-objs += isadma.o endif diff --git a/sound/core/info.c b/sound/core/info.c index 37024d68a26e..39f9b97d9219 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -566,7 +566,6 @@ int __init snd_info_init(void) } #endif snd_info_version_init(); - snd_memory_info_init(); snd_minor_info_init(); snd_minor_info_oss_init(); snd_card_info_init(); @@ -578,7 +577,6 @@ int __exit snd_info_done(void) snd_card_info_done(); snd_minor_info_oss_done(); snd_minor_info_done(); - snd_memory_info_done(); snd_info_version_done(); if (snd_proc_root) { #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) diff --git a/sound/core/memory.c b/sound/core/memory.c index b99343616f81..862d62d2e144 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -1,7 +1,7 @@ /* * Copyright (c) by Jaroslav Kysela * - * Memory allocation helpers. + * Misc memory accessors * * * This program is free software; you can redistribute it and/or modify @@ -20,168 +20,9 @@ * */ -#include +#include #include #include -#include -#include -#include -#include -#include -#include - -/* - * memory allocation helpers and debug routines - */ - -#ifdef CONFIG_SND_DEBUG_MEMORY - -struct snd_alloc_track { - unsigned long magic; - void *caller; - size_t size; - struct list_head list; - long data[0]; -}; - -#define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data) - -static long snd_alloc_kmalloc; -static LIST_HEAD(snd_alloc_kmalloc_list); -static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); -#define KMALLOC_MAGIC 0x87654321 -static snd_info_entry_t *snd_memory_info_entry; - -void __init snd_memory_init(void) -{ - snd_alloc_kmalloc = 0; -} - -void snd_memory_done(void) -{ - struct list_head *head; - struct snd_alloc_track *t; - - if (snd_alloc_kmalloc > 0) - snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc); - list_for_each_prev(head, &snd_alloc_kmalloc_list) { - t = list_entry(head, struct snd_alloc_track, list); - if (t->magic != KMALLOC_MAGIC) { - snd_printk(KERN_ERR "Corrupted kmalloc\n"); - break; - } - snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); - } -} - -static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) -{ - unsigned long cpu_flags; - struct snd_alloc_track *t; - void *ptr; - - ptr = snd_wrapper_kmalloc(size + sizeof(struct snd_alloc_track), flags); - if (ptr != NULL) { - t = (struct snd_alloc_track *)ptr; - t->magic = KMALLOC_MAGIC; - t->caller = caller; - spin_lock_irqsave(&snd_alloc_kmalloc_lock, cpu_flags); - list_add_tail(&t->list, &snd_alloc_kmalloc_list); - spin_unlock_irqrestore(&snd_alloc_kmalloc_lock, cpu_flags); - t->size = size; - snd_alloc_kmalloc += size; - ptr = t->data; - } - return ptr; -} - -#define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); -void *snd_hidden_kmalloc(size_t size, gfp_t flags) -{ - return _snd_kmalloc(size, flags); -} - -void *snd_hidden_kzalloc(size_t size, gfp_t flags) -{ - void *ret = _snd_kmalloc(size, flags); - if (ret) - memset(ret, 0, size); - return ret; -} -EXPORT_SYMBOL(snd_hidden_kzalloc); - -void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags) -{ - void *ret = NULL; - if (n != 0 && size > INT_MAX / n) - return ret; - return snd_hidden_kzalloc(n * size, flags); -} - -void snd_hidden_kfree(const void *obj) -{ - unsigned long flags; - struct snd_alloc_track *t; - if (obj == NULL) - return; - t = snd_alloc_track_entry(obj); - if (t->magic != KMALLOC_MAGIC) { - snd_printk(KERN_WARNING "bad kfree (called from %p)\n", __builtin_return_address(0)); - return; - } - spin_lock_irqsave(&snd_alloc_kmalloc_lock, flags); - list_del(&t->list); - spin_unlock_irqrestore(&snd_alloc_kmalloc_lock, flags); - t->magic = 0; - snd_alloc_kmalloc -= t->size; - obj = t; - snd_wrapper_kfree(obj); -} - -char *snd_hidden_kstrdup(const char *s, gfp_t flags) -{ - int len; - char *buf; - - if (!s) return NULL; - - len = strlen(s) + 1; - buf = _snd_kmalloc(len, flags); - if (buf) - memcpy(buf, s, len); - return buf; -} - -static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) -{ - snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); -} - -int __init snd_memory_info_init(void) -{ - snd_info_entry_t *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "meminfo", NULL); - if (entry) { - entry->c.text.read_size = 256; - entry->c.text.read = snd_memory_info_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_memory_info_entry = entry; - return 0; -} - -int __exit snd_memory_info_done(void) -{ - if (snd_memory_info_entry) - snd_info_unregister(snd_memory_info_entry); - return 0; -} - -#endif /* CONFIG_SND_DEBUG_MEMORY */ /** * copy_to_user_fromio - copy data from mmio-space to user-space diff --git a/sound/core/misc.c b/sound/core/misc.c index 3eddfdede9f3..b53e563c09e6 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -30,7 +30,7 @@ void release_and_free_resource(struct resource *res) { if (res) { release_resource(res); - kfree_nocheck(res); + kfree(res); } } diff --git a/sound/core/sound.c b/sound/core/sound.c index e94eebd8ad6f..dee602245fe8 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -350,9 +350,7 @@ static int __init alsa_sound_init(void) devfs_remove("snd"); return -EIO; } - snd_memory_init(); if (snd_info_init() < 0) { - snd_memory_done(); unregister_chrdev(major, "alsa"); devfs_remove("snd"); return -ENOMEM; @@ -381,7 +379,6 @@ static void __exit alsa_sound_exit(void) #endif snd_info_minor_unregister(); snd_info_done(); - snd_memory_done(); if (unregister_chrdev(major, "alsa") != 0) snd_printk(KERN_ERR "unable to unregister major device number %d\n", major); devfs_remove("snd"); @@ -403,12 +400,6 @@ EXPORT_SYMBOL(snd_register_oss_device); EXPORT_SYMBOL(snd_unregister_oss_device); #endif /* memory.c */ -#ifdef CONFIG_SND_DEBUG_MEMORY -EXPORT_SYMBOL(snd_hidden_kmalloc); -EXPORT_SYMBOL(snd_hidden_kcalloc); -EXPORT_SYMBOL(snd_hidden_kfree); -EXPORT_SYMBOL(snd_hidden_kstrdup); -#endif EXPORT_SYMBOL(copy_to_user_fromio); EXPORT_SYMBOL(copy_from_user_toio); /* init.c */ @@ -491,9 +482,4 @@ EXPORT_SYMBOL(snd_verbose_printk); #endif #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) EXPORT_SYMBOL(snd_verbose_printd); -#endif - /* wrappers */ -#ifdef CONFIG_SND_DEBUG_MEMORY -EXPORT_SYMBOL(snd_wrapper_kmalloc); -EXPORT_SYMBOL(snd_wrapper_kfree); #endif -- cgit v1.2.3 From b709e57440b9d5f38b8c73e1310127d51777bba0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 Oct 2005 17:28:58 +0200 Subject: [ALSA] Add the missing forward declration Modules: ALSA Core Added the missing forward declaration before function prototypes. Signed-off-by: Takashi Iwai --- include/sound/core.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/sound/core.h b/include/sound/core.h index ed56a356ab7d..642ddfbc6325 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -339,6 +339,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); #endif /* misc.c */ +struct resource; void release_and_free_resource(struct resource *res); #ifdef CONFIG_SND_VERBOSE_PRINTK -- cgit v1.2.3 From de24214d0c8e78134875752619f99b9e5824c196 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 12 Oct 2005 17:12:31 +0200 Subject: [ALSA] timers: add module refcounting for global timers Modules: RTC timer driver,Timer Midlevel Add a module pointer to the timer structure and use it for refcounting instead of the card's module pointer to prevent the global timer modules (rtctimer and hpetimer) from being removed while in use. Signed-off-by: Clemens Ladisch --- include/sound/timer.h | 1 + sound/core/rtctimer.c | 4 +++- sound/core/timer.c | 7 ++++--- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/sound/timer.h b/include/sound/timer.h index 1898511a0f38..b55f38ae56e1 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -88,6 +88,7 @@ struct _snd_timer_hardware { struct _snd_timer { snd_timer_class_t tmr_class; snd_card_t *card; + struct module *module; int tmr_device; int tmr_subdevice; char id[64]; diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 8762ff8938c2..c3c18568207e 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -124,7 +124,8 @@ static int __init rtctimer_init(void) if (rtctimer_freq < 2 || rtctimer_freq > 8192 || (rtctimer_freq & (rtctimer_freq - 1)) != 0) { - snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq); + snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", + rtctimer_freq); return -EINVAL; } @@ -133,6 +134,7 @@ static int __init rtctimer_init(void) if (err < 0) return err; + timer->module = THIS_MODULE; strcpy(timer->name, "RTC timer"); timer->hw = rtc_hw; timer->hw.resolution = NANO_SEC / rtctimer_freq; diff --git a/sound/core/timer.c b/sound/core/timer.c index b02681eaea75..c8496c7b8df8 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -113,7 +113,7 @@ static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *ti INIT_LIST_HEAD(&timeri->slave_active_head); timeri->timer = timer; - if (timer && timer->card && !try_module_get(timer->card->module)) { + if (timer && !try_module_get(timer->module)) { kfree(timeri->owner); kfree(timeri); return NULL; @@ -363,8 +363,8 @@ int snd_timer_close(snd_timer_instance_t * timeri) timeri->private_free(timeri); kfree(timeri->owner); kfree(timeri); - if (timer && timer->card) - module_put(timer->card->module); + if (timer) + module_put(timer->module); return 0; } @@ -787,6 +787,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t * spin_lock_init(&timer->lock); tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer); if (card != NULL) { + timer->module = card->module; if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) { snd_timer_free(timer); return err; -- cgit v1.2.3 From 3939e7142da722324ab07d244a9736b0fa59c362 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 24 Oct 2005 17:02:03 +0200 Subject: [ALSA] clean up device types symbols Modules: ALSA Core,ALSA Minor Numbers Remove the unused and undefined symbols SNDRV_DEVICE_TYPE_{MIXER, PCM_PLOOP,PCM_CLOOP}, and introduce a new symbol SNDRV_MINOR_GLOBAL for non-card-specific devices like the sequencer or the timer. Signed-off-by: Clemens Ladisch --- include/sound/minors.h | 8 +++----- sound/core/sound.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/sound/minors.h b/include/sound/minors.h index b7b0d8309449..a17b5c9961bb 100644 --- a/include/sound/minors.h +++ b/include/sound/minors.h @@ -27,8 +27,9 @@ #define SNDRV_MINOR(card, dev) (((card) << 5) | (dev)) #define SNDRV_MINOR_CONTROL 0 /* 0 - 0 */ -#define SNDRV_MINOR_SEQUENCER 1 -#define SNDRV_MINOR_TIMER (1+32) +#define SNDRV_MINOR_GLOBAL 1 /* 1 */ +#define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) +#define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32) #define SNDRV_MINOR_HWDEP 4 /* 4 - 7 */ #define SNDRV_MINOR_HWDEPS 4 #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ @@ -39,12 +40,9 @@ #define SNDRV_DEVICE_TYPE_CONTROL SNDRV_MINOR_CONTROL #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP -#define SNDRV_DEVICE_TYPE_MIXER SNDRV_MINOR_MIXER #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI #define SNDRV_DEVICE_TYPE_PCM_PLAYBACK SNDRV_MINOR_PCM_PLAYBACK -#define SNDRV_DEVICE_TYPE_PCM_PLOOP SNDRV_MINOR_PCM_PLOOP #define SNDRV_DEVICE_TYPE_PCM_CAPTURE SNDRV_MINOR_PCM_CAPTURE -#define SNDRV_DEVICE_TYPE_PCM_CLOOP SNDRV_MINOR_PCM_CLOOP #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER diff --git a/sound/core/sound.c b/sound/core/sound.c index dee602245fe8..1139dd8ca8eb 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -130,7 +130,7 @@ static int snd_open(struct inode *inode, struct file *file) struct file_operations *old_fops; int err = 0; - if (dev != SNDRV_MINOR_SEQUENCER && dev != SNDRV_MINOR_TIMER) { + if (dev != SNDRV_MINOR_GLOBAL) { if (snd_cards[card] == NULL) { #ifdef CONFIG_KMOD snd_request_card(card); @@ -287,7 +287,7 @@ static void snd_minor_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buf for (card = 0; card < SNDRV_CARDS; card++) { list_for_each(list, &snd_minors_hash[card]) { mptr = list_entry(list, snd_minor_t, list); - if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_SEQUENCER) { + if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_GLOBAL) { if ((device = mptr->device) >= 0) snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, device, mptr->comment); else -- cgit v1.2.3 From f1902860161ff212c515e7ea629e880fec856a37 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 24 Oct 2005 17:05:03 +0200 Subject: [ALSA] fix improper CONFIG_SND_MAJOR usage Modules: HWDEP Midlevel,PCM Midlevel,RawMidi Midlevel,ALSA Core Replace usage of CONFIG_SND_MAJOR with snd_major, where appropriate. Signed-off-by: Clemens Ladisch --- include/sound/core.h | 1 + sound/core/hwdep.c | 10 +++------- sound/core/pcm_native.c | 1 - sound/core/rawmidi.c | 12 ++++-------- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/sound/core.h b/include/sound/core.h index 642ddfbc6325..2be65ad2fd83 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -255,6 +255,7 @@ typedef struct _snd_minor snd_minor_t; /* sound.c */ +extern int snd_major; extern int snd_ecards_limit; void snd_request_card(int card); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 9383f1294fb5..e91cee35a4b9 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -81,20 +81,16 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) int err; wait_queue_t wait; - switch (major) { - case CONFIG_SND_MAJOR: + if (major == snd_major) { cardnum = SNDRV_MINOR_CARD(iminor(inode)); device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP; - break; #ifdef CONFIG_SND_OSSEMUL - case SOUND_MAJOR: + } else if (major == SOUND_MAJOR) { cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); device = 0; - break; #endif - default: + } else return -ENXIO; - } cardnum %= SNDRV_CARDS; device %= SNDRV_MINOR_HWDEPS; hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device]; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a1924f12d8fc..16e252f54954 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1522,7 +1522,6 @@ static int snd_pcm_drop(snd_pcm_substream_t *substream) /* WARNING: Don't forget to fput back the file */ -extern int snd_major; static struct file *snd_pcm_file_fd(int fd) { struct file *file; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7c20eafecb8a..d033e61c05c7 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -378,24 +378,20 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) struct list_head *list; snd_ctl_file_t *kctl; - switch (maj) { - case CONFIG_SND_MAJOR: + if (maj == snd_major) { cardnum = SNDRV_MINOR_CARD(iminor(inode)); cardnum %= SNDRV_CARDS; device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI; device %= SNDRV_MINOR_RAWMIDIS; - break; #ifdef CONFIG_SND_OSSEMUL - case SOUND_MAJOR: + } else if (maj == SOUND_MAJOR) { cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); cardnum %= SNDRV_CARDS; device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ? midi_map[cardnum] : amidi_map[cardnum]; - break; #endif - default: + } else return -ENXIO; - } rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device]; if (rmidi == NULL) @@ -411,7 +407,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (err < 0) return -ENODEV; fflags = snd_rawmidi_file_flags(file); - if ((file->f_flags & O_APPEND) || maj != CONFIG_SND_MAJOR) /* OSS emul? */ + if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ fflags |= SNDRV_RAWMIDI_LFLG_APPEND; fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK; rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); -- cgit v1.2.3 From 9529a5bae10118fd08edfd667cac19f94fb7264a Mon Sep 17 00:00:00 2001 From: Lee Revell Date: Tue, 25 Oct 2005 11:25:29 +0200 Subject: [ALSA] emu10k1 - Use 31 bit DMA mask for Audigy Modules: EMU10K1/EMU10K2 driver It appears that either the Audigy DMA engine or the Linux kernel cannot handle 32 bit DMA with this device. Problem manifests as noise when using more than 2GB of RAM, possibly only on 64 bit machines. The OSS driver actually uses a 29 bit DMA mask for both devices, this seems like overkill for now. Signed-off-by: Lee Revell Signed-off-by: Takashi Iwai --- include/sound/emu10k1.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 46e3c0bf3c94..8411c7ef6f11 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -48,7 +48,8 @@ /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ -#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit */ +#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */ + /* See ALSA bug #1276 - rlrevell */ #define TMEMSIZE 256*1024 #define TMEMSIZEREG 4 -- cgit v1.2.3 From 7866f6492856dde7d70e4f878e3893e1f91216ce Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Fri, 4 Nov 2005 17:15:44 +0000 Subject: [ARM] 3086/1: ixp2xxx error irq handling Patch from Dave Jiang This provides support for IXP2xxx error interrupt handling. Previously there was a patch to remove this (although the original stuff was broken). Well, now the error bits are needed again. These are used extensively by the micro-engine drivers according to Deepak and also we will need it for the new EDAC code that Alan Cox is trying to push into the main kernel. Re-submit of 3072/1, generated against git tree pulled today. AFAICT, this git tree pulled in all the ARM changes that's in arm.diff. Please let me know if there are additional changes. Thx! Signed-off-by: Dave Jiang Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp2000/core.c | 46 +++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-ixp2000/irqs.h | 35 +++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index c93a98b2a32c..df140962bb0f 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -402,6 +402,40 @@ static void ixp2000_pci_irq_unmask(unsigned int irq) ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27))); } +/* + * Error interrupts. These are used extensively by the microengine drivers + */ +static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) +{ + int i; + unsigned long status = *IXP2000_IRQ_ERR_STATUS; + + for(i = 31; i >= 0; i--) { + if(status & (1 << i)) { + desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; + desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs); + } + } +} + +static void ixp2000_err_irq_mask(unsigned int irq) +{ + ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR, + (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))); +} + +static void ixp2000_err_irq_unmask(unsigned int irq) +{ + ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET, + (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))); +} + +static struct irqchip ixp2000_err_irq_chip = { + .ack = ixp2000_err_irq_mask, + .mask = ixp2000_err_irq_mask, + .unmask = ixp2000_err_irq_unmask +}; + static struct irqchip ixp2000_pci_irq_chip = { .ack = ixp2000_pci_irq_mask, .mask = ixp2000_pci_irq_mask, @@ -459,6 +493,18 @@ void __init ixp2000_init_irq(void) } else set_irq_flags(irq, 0); } + for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) { + if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) & + IXP2000_VALID_ERR_IRQ_MASK) { + set_irq_chip(irq, &ixp2000_err_irq_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + else + set_irq_flags(irq, 0); + } + set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler); + /* * GPIO IRQs are invalid until someone sets the interrupt mode * by calling set_irq_type(). diff --git a/include/asm-arm/arch-ixp2000/irqs.h b/include/asm-arm/arch-ixp2000/irqs.h index 0deb96c12adb..62f09c7ff420 100644 --- a/include/asm-arm/arch-ixp2000/irqs.h +++ b/include/asm-arm/arch-ixp2000/irqs.h @@ -67,12 +67,45 @@ #define IRQ_IXP2000_PCIA 40 #define IRQ_IXP2000_PCIB 41 -#define NR_IXP2000_IRQS 42 +/* Int sources from IRQ_ERROR_STATUS */ +#define IRQ_IXP2000_DRAM0_MIN_ERR 42 +#define IRQ_IXP2000_DRAM0_MAJ_ERR 43 +#define IRQ_IXP2000_DRAM1_MIN_ERR 44 +#define IRQ_IXP2000_DRAM1_MAJ_ERR 45 +#define IRQ_IXP2000_DRAM2_MIN_ERR 46 +#define IRQ_IXP2000_DRAM2_MAJ_ERR 47 +/* 48-57 reserved */ +#define IRQ_IXP2000_SRAM0_ERR 58 +#define IRQ_IXP2000_SRAM1_ERR 59 +#define IRQ_IXP2000_SRAM2_ERR 60 +#define IRQ_IXP2000_SRAM3_ERR 61 +/* 62-65 reserved */ +#define IRQ_IXP2000_MEDIA_ERR 66 +#define IRQ_IXP2000_PCI_ERR 67 +#define IRQ_IXP2000_SP_INT 68 + +#define NR_IXP2000_IRQS 69 #define IXP2000_BOARD_IRQ(x) (NR_IXP2000_IRQS + (x)) #define IXP2000_BOARD_IRQ_MASK(irq) (1 << (irq - NR_IXP2000_IRQS)) +#define IXP2000_ERR_IRQ_MASK(irq) ( 1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) +#define IXP2000_VALID_ERR_IRQ_MASK (\ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM0_MIN_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM0_MAJ_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM1_MIN_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM1_MAJ_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM2_MIN_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM2_MAJ_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM0_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM1_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM2_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM3_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_MEDIA_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_PCI_ERR) | \ + IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SP_INT) ) + /* * This allows for all the on-chip sources plus up to 32 CPLD based * IRQs. Should be more than enough. -- cgit v1.2.3 From d56c524afaa87ae224b5821ef101891ce076c321 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 4 Nov 2005 17:28:34 +0000 Subject: [PATCH] ARM: Reverted 2918/1: [update] Base port of Comdial MP1000 platfrom No longer maintained --- arch/arm/Kconfig | 3 +- arch/arm/boot/compressed/head.S | 3 +- arch/arm/configs/mp1000_defconfig | 897 -------------------------- arch/arm/mach-clps711x/Kconfig | 11 - arch/arm/mach-clps711x/Makefile | 1 - arch/arm/mach-clps711x/mp1000-mach.c | 49 -- arch/arm/mach-clps711x/mp1000-mm.c | 47 -- arch/arm/mach-clps711x/mp1000-seprom.c | 195 ------ drivers/serial/clps711x.c | 9 - include/asm-arm/arch-clps711x/hardware.h | 117 ---- include/asm-arm/arch-clps711x/mp1000-seprom.h | 77 --- 11 files changed, 2 insertions(+), 1407 deletions(-) delete mode 100644 arch/arm/configs/mp1000_defconfig delete mode 100644 arch/arm/mach-clps711x/mp1000-mach.c delete mode 100644 arch/arm/mach-clps711x/mp1000-mm.c delete mode 100644 arch/arm/mach-clps711x/mp1000-seprom.c delete mode 100644 include/asm-arm/arch-clps711x/mp1000-seprom.h (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6b12d71978de..296bc03d1cf1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -704,8 +704,7 @@ source "drivers/acorn/block/Kconfig" if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \ || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \ - || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \ - || MACH_MP1000 + || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE source "drivers/ide/Kconfig" endif diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index a54d2eb64892..7c7f475e213e 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -39,8 +39,7 @@ defined(CONFIG_ARCH_IXP4XX) || \ defined(CONFIG_ARCH_IXP2000) || \ defined(CONFIG_ARCH_LH7A40X) || \ - defined(CONFIG_ARCH_OMAP) || \ - defined(CONFIG_MACH_MP1000) + defined(CONFIG_ARCH_OMAP) .macro loadsp, rb addruart \rb .endm diff --git a/arch/arm/configs/mp1000_defconfig b/arch/arm/configs/mp1000_defconfig deleted file mode 100644 index d2cbc6fada1d..000000000000 --- a/arch/arm/configs/mp1000_defconfig +++ /dev/null @@ -1,897 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-rc1 -# Fri Sep 16 15:48:13 2005 -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_CALIBRATE_DELAY=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -CONFIG_ARCH_CLPS711X=y -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CEIVA is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -CONFIG_MACH_MP1000=y -CONFIG_MP1000_90MHZ=y - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_ARM720T=y -CONFIG_CPU_32v4=y -CONFIG_CPU_ABRT_LV4T=y -CONFIG_CPU_CACHE_V4=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WT=y -CONFIG_CPU_TLB_V4WT=y - -# -# Processor Features -# -CONFIG_ARM_THUMB=y - -# -# Bus support -# -CONFIG_ISA_DMA_API=y - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -# CONFIG_SMP is not set -CONFIG_PREEMPT=y -# CONFIG_NO_IDLE_HZ is not set -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyCL,38400 root=/dev/discs/disc0/part1 ip=any cs89x0_media=rj45" -# CONFIG_XIP_KERNEL is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=y -# CONFIG_ARTHUR is not set - -# -# Power management options -# -# CONFIG_PM is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_IEEE80211 is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=3 -# CONFIG_MTD_CONCAT is not set -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=m -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 -CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=m -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=m -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -# CONFIG_MTD_CFI_I1 is not set -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_OTP is not set -CONFIG_MTD_CFI_INTELEXT=m -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=m -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_XIP is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=m -CONFIG_MTD_PHYSMAP_START=0x0000000 -CONFIG_MTD_PHYSMAP_LEN=0x4000000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 -# CONFIG_MTD_ARM_INTEGRATOR is not set -CONFIG_MTD_EDB7312=m -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_MP1000=y -CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_NANDSIM is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=2 -CONFIG_BLK_DEV_RAM_SIZE=16384 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_IDE_GENERIC is not set -CONFIG_IDE_ARM=y -CONFIG_BLK_DEV_IDE_MP1000=y -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -CONFIG_BLK_DEV_DM=y -# CONFIG_DM_CRYPT is not set -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set -# CONFIG_DM_MULTIPATH is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# - -# -# Network device support -# -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# PHY device support -# -# CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_SMC91X is not set -# CONFIG_DM9000 is not set -CONFIG_CS89x0=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -CONFIG_INPUT_EVBUG=y - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_LIBPS2 is not set -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=2 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CLPS711X=y -CONFIG_SERIAL_CLPS711X_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_NVRAM=y -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Hardware Monitoring support -# -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Misc devices -# - -# -# Multimedia Capabilities Port drivers -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -# CONFIG_EXT2_FS_SECURITY is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set -CONFIG_QUOTACTL=y -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -CONFIG_NFS_V4=y -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V3_ACL is not set -CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=y -CONFIG_RPCSEC_GSS_KRB5=y -# CONFIG_RPCSEC_GSS_SPKM3 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_EXPERIMENTAL is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_KERNEL=y -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_PREEMPT=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_FS is not set -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_WAITQ=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=m -CONFIG_ZLIB_DEFLATE=m diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig index d5c155045762..0793dcf54f2e 100644 --- a/arch/arm/mach-clps711x/Kconfig +++ b/arch/arm/mach-clps711x/Kconfig @@ -69,17 +69,6 @@ config EP72XX_ROM_BOOT You almost surely want to say N here. -config MACH_MP1000 - bool "MACH_MP1000" - help - Say Y if you intend to run the kernel on the Comdial MP1000 platform. - -config MP1000_90MHZ - bool "MP1000_90MHZ" - depends on MACH_MP1000 - help - Say Y if you have the MP1000 configured to be set at 90MHZ rather than 74MHZ - endmenu endif diff --git a/arch/arm/mach-clps711x/Makefile b/arch/arm/mach-clps711x/Makefile index 8a6dc1ccf8fe..4a197315f0cf 100644 --- a/arch/arm/mach-clps711x/Makefile +++ b/arch/arm/mach-clps711x/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_ARCH_CDB89712) += cdb89712.o obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o obj-$(CONFIG_ARCH_EDB7211) += edb7211-arch.o edb7211-mm.o obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o -obj-$(CONFIG_MACH_MP1000) += mp1000-mach.o mp1000-mm.o mp1000-seprom.o obj-$(CONFIG_ARCH_P720T) += p720t.o leds-$(CONFIG_ARCH_P720T) += p720t-leds.o obj-$(CONFIG_LEDS) += $(leds-y) diff --git a/arch/arm/mach-clps711x/mp1000-mach.c b/arch/arm/mach-clps711x/mp1000-mach.c deleted file mode 100644 index c2816bcde5e7..000000000000 --- a/arch/arm/mach-clps711x/mp1000-mach.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * linux/arch/arm/mach-mp1000/mp1000.c - * - * Copyright (C) 2005 Comdial Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include - -#include -#include -#include -#include - -#include "common.h" - -extern void mp1000_map_io(void); - -static void __init mp1000_init(void) -{ - seprom_init(); -} - -MACHINE_START(MP1000, "Comdial MP1000") - /* Maintainer: Jon Ringle */ - .phys_ram = 0xc0000000, - .phys_io = 0x80000000, - .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, - .boot_params = 0xc0015100, - .map_io = mp1000_map_io, - .init_irq = clps711x_init_irq, - .init_machine = mp1000_init, - .timer = &clps711x_timer, -MACHINE_END - diff --git a/arch/arm/mach-clps711x/mp1000-mm.c b/arch/arm/mach-clps711x/mp1000-mm.c deleted file mode 100644 index 20e810b0ec0c..000000000000 --- a/arch/arm/mach-clps711x/mp1000-mm.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * linux/arch/arm/mach-mp1000/mm.c - * - * Extra MM routines for the MP1000 - * - * Copyright (C) 2005 Comdial Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include - -#include -#include -#include -#include - -#include - -extern void clps711x_map_io(void); - -static struct map_desc mp1000_io_desc[] __initdata = { - { MP1000_EIO_BASE, MP1000_EIO_START, MP1000_EIO_SIZE, MT_DEVICE }, - { MP1000_FIO_BASE, MP1000_FIO_START, MP1000_FIO_SIZE, MT_DEVICE }, - { MP1000_LIO_BASE, MP1000_LIO_START, MP1000_LIO_SIZE, MT_DEVICE }, - { MP1000_NIO_BASE, MP1000_NIO_START, MP1000_NIO_SIZE, MT_DEVICE }, - { MP1000_IDE_BASE, MP1000_IDE_START, MP1000_IDE_SIZE, MT_DEVICE }, - { MP1000_DSP_BASE, MP1000_DSP_START, MP1000_DSP_SIZE, MT_DEVICE } -}; - -void __init mp1000_map_io(void) -{ - clps711x_map_io(); - iotable_init(mp1000_io_desc, ARRAY_SIZE(mp1000_io_desc)); -} diff --git a/arch/arm/mach-clps711x/mp1000-seprom.c b/arch/arm/mach-clps711x/mp1000-seprom.c deleted file mode 100644 index b22d0bebb851..000000000000 --- a/arch/arm/mach-clps711x/mp1000-seprom.c +++ /dev/null @@ -1,195 +0,0 @@ -/*` - * mp1000-seprom.c - * - * This file contains the Serial EEPROM code for the MP1000 board - * - * Copyright (C) 2005 Comdial Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include - -/* If SepromInit() can initialize and checksum the seprom successfully, */ -/* then it will point seprom_data_ptr at the shadow copy. */ - -static eeprom_struct seprom_data; /* shadow copy of seprom content */ - -eeprom_struct *seprom_data_ptr = 0; /* 0 => not initialized */ - -/* - * Port D Bit 5 is Chip Select for EEPROM - * Port E Bit 0 is Input, Data out from EEPROM - * Port E Bit 1 is Output, Data in to EEPROM - * Port E Bit 2 is Output, CLK to EEPROM - */ - -static char *port_d_ptr = (char *)(CLPS7111_VIRT_BASE + PDDR); -static char *port_e_ptr = (char *)(CLPS7111_VIRT_BASE + PEDR); - -#define NO_OF_SHORTS 64 // Device is 64 x 16 bits -#define ENABLE_RW 0 -#define DISABLE_RW 1 - -static inline void toggle_seprom_clock(void) -{ - *port_e_ptr |= HwPortESepromCLK; - *port_e_ptr &= ~(HwPortESepromCLK); -} - -static inline void select_eeprom(void) -{ - *port_d_ptr |= HwPortDEECS; - *port_e_ptr &= ~(HwPortESepromCLK); -} - -static inline void deselect_eeprom(void) -{ - *port_d_ptr &= ~(HwPortDEECS); - *port_e_ptr &= ~(HwPortESepromDIn); -} - -/* - * GetSepromDataPtr - returns pointer to shadow (RAM) copy of seprom - * and returns 0 if seprom is not initialized or - * has a checksum error. - */ - -eeprom_struct* get_seprom_ptr(void) -{ - return seprom_data_ptr; -} - -unsigned char* get_eeprom_mac_address(void) -{ - return seprom_data_ptr->variant.eprom_struct.mac_Address; -} - -/* - * ReadSProm, Physically reads data from the Serial PROM - */ -static void read_sprom(short address, int length, eeprom_struct *buffer) -{ - short data = COMMAND_READ | (address & 0x3F); - short bit; - int i; - - select_eeprom(); - - // Clock in 9 bits of the command - for (i = 0, bit = 0x100; i < 9; i++, bit >>= 1) { - if (data & bit) - *port_e_ptr |= HwPortESepromDIn; - else - *port_e_ptr &= ~(HwPortESepromDIn); - - toggle_seprom_clock(); - } - - // - // Now read one or more shorts of data from the Seprom - // - while (length-- > 0) { - data = 0; - - // Read 16 bits at a time - for (i = 0; i < 16; i++) { - data <<= 1; - toggle_seprom_clock(); - data |= *port_e_ptr & HwPortESepromDOut; - - } - - buffer->variant.eprom_short_data[address++] = data; - } - - deselect_eeprom(); - - return; -} - - - -/* - * ReadSerialPROM - * - * Input: Pointer to array of 64 x 16 Bits - * - * Output: if no problem reading data is filled in - */ -static void read_serial_prom(eeprom_struct *data) -{ - read_sprom(0, 64, data); -} - - -// -// Compute Serial EEPROM checksum -// -// Input: Pointer to struct with Eprom data -// -// Output: The computed Eprom checksum -// -static short compute_seprom_checksum(eeprom_struct *data) -{ - short checksum = 0; - int i; - - for (i = 0; i < 126; i++) { - checksum += (short)data->variant.eprom_byte_data[i]; - } - - return((short)(0x5555 - (checksum & 0xFFFF))); -} - -// -// Make sure the data port bits for the SEPROM are correctly initialised -// - -void __init seprom_init(void) -{ - short checksum; - - // Init Port D - *(char *)(CLPS7111_VIRT_BASE + PDDDR) = 0x0; - *(char *)(CLPS7111_VIRT_BASE + PDDR) = 0x15; - - // Init Port E - *(int *)(CLPS7111_VIRT_BASE + PEDDR) = 0x06; - *(int *)(CLPS7111_VIRT_BASE + PEDR) = 0x04; - - // - // Make sure that EEPROM struct size never exceeds 128 bytes - // - if (sizeof(eeprom_struct) > 128) { - panic("Serial PROM struct size > 128, aborting read\n"); - } - - read_serial_prom(&seprom_data); - - checksum = compute_seprom_checksum(&seprom_data); - - if (checksum != seprom_data.variant.eprom_short_data[63]) { - panic("Serial EEPROM checksum failed\n"); - } - - seprom_data_ptr = &seprom_data; -} - diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 6a67e8f585b3..87ef368384fb 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -408,11 +408,7 @@ static struct uart_port clps711x_ports[UART_NR] = { { .iobase = SYSCON1, .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ -#ifdef CONFIG_MP1000_90MHZ - .uartclk = 4515840, -#else .uartclk = 3686400, -#endif .fifosize = 16, .ops = &clps711x_pops, .line = 0, @@ -421,11 +417,7 @@ static struct uart_port clps711x_ports[UART_NR] = { { .iobase = SYSCON2, .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */ -#ifdef CONFIG_MP1000_90MHZ - .uartclk = 4515840, -#else .uartclk = 3686400, -#endif .fifosize = 16, .ops = &clps711x_pops, .line = 1, @@ -559,7 +551,6 @@ console_initcall(clps711xuart_console_init); static struct uart_driver clps711x_reg = { .driver_name = "ttyCL", .dev_name = "ttyCL", - .devfs_name = "ttyCL", .major = SERIAL_CLPS711X_MAJOR, .minor = SERIAL_CLPS711X_MINOR, .nr = UART_NR, diff --git a/include/asm-arm/arch-clps711x/hardware.h b/include/asm-arm/arch-clps711x/hardware.h index f864c367c934..1386871e1a5a 100644 --- a/include/asm-arm/arch-clps711x/hardware.h +++ b/include/asm-arm/arch-clps711x/hardware.h @@ -235,121 +235,4 @@ #define CEIVA_PB0_BLK_BTN (1<<0) #endif // #if defined (CONFIG_ARCH_CEIVA) -#if defined (CONFIG_MACH_MP1000) -/* NOR FLASH */ -#define MP1000_NIO_BASE 0xf9000000 /* virtual */ -#define MP1000_NIO_START CS0_PHYS_BASE /* physical */ -#define MP1000_NIO_SIZE 0x00400000 - -/* DSP Interface */ -#define MP1000_DSP_BASE 0xfa000000 /* virtual */ -#define MP1000_DSP_START CS1_PHYS_BASE /* physical */ -#define MP1000_DSP_SIZE 0x00100000 - -/* LCD, DAA/DSP, RTC, DAA RW Reg all in CS2 */ -#define MP1000_LIO_BASE 0xfb000000 /* virtual */ -#define MP1000_LIO_START CS2_PHYS_BASE /* physical */ -#define MP1000_LIO_SIZE 0x00100000 - -/* NAND FLASH */ -#define MP1000_FIO_BASE 0xfc000000 /* virtual */ -#define MP1000_FIO_START CS3_PHYS_BASE /* physical */ -#define MP1000_FIO_SIZE 0x00800000 - -/* Ethernet */ -#define MP1000_EIO_BASE 0xfd000000 /* virtual */ -#define MP1000_EIO_START CS4_PHYS_BASE /* physical */ -#define MP1000_EIO_SIZE 0x00100000 - -#define MP1000_LCD_OFFSET 0x00000000 /* LCD offset in CS2 */ -#define MP1000_DDD_OFFSET 0x00001000 /* DAA/DAI/DSP sft reset offst*/ -#define MP1000_RTC_OFFSET 0x00002000 /* RTC offset in CS2 */ -#define MP1000_DAA_OFFSET 0x00003000 /* DAA RW reg offset in CS2 */ - -/* IDE */ -#define MP1000_IDE_BASE 0xfe000000 /* virtual */ -#define MP1000_IDE_START CS5_PHYS_BASE /* physical */ -#define MP1000_IDE_SIZE 0x00100000 /* actually it's only 0x1000 */ - -#define IRQ_HARDDISK IRQ_EINT2 - -/* - * IDE registers definition - */ - -#define IDE_CONTROL_BASE (MP1000_IDE_BASE + 0x1000) -#define IDE_BASE_OFF (MP1000_IDE_BASE) - -#define IDE_WRITE_DEVICE_DATA (IDE_BASE_OFF + 0x0) -#define IDE_FEATURES_REGISTER (IDE_BASE_OFF + 0x2) -#define IDE_SECTOR_COUNT_REGISTER (IDE_BASE_OFF + 0x4) -#define IDE_SECTOR_NUMBER_REGISTER (IDE_BASE_OFF + 0x6) -#define IDE_CYLINDER_LOW_REGISTER (IDE_BASE_OFF + 0x8) -#define IDE_CYLINDER_HIGH_REGISTER (IDE_BASE_OFF + 0xa) -#define IDE_DEVICE_HEAD_REGISTER (IDE_BASE_OFF + 0xc) -#define IDE_COMMAND_DATA_REGISTER (IDE_BASE_OFF + 0xe) -#define IDE_DEVICE_CONTROL_REGISTER (IDE_CONTROL_BASE + 0xc) - -#define IDE_IRQ IRQ_EINT2 - - -#define RTC_PORT(x) (MP1000_LIO_BASE+0x2000 + (x*2)) -#define RTC_ALWAYS_BCD 0 - -/* -// Definitions of the bit fields in the HwPortA register for the -// MP1000 board. -*/ -#define HwPortAKeyboardRow1 0x00000001 -#define HwPortAKeyboardRow2 0x00000002 -#define HwPortAKeyboardRow3 0x00000004 -#define HwPortAKeyboardRow4 0x00000008 -#define HwPortAKeyboardRow5 0x00000010 -#define HwPortAKeyboardRow6 0x00000020 -#define HwPortALCDEnable 0x00000040 -#define HwPortAOffhook 0x00000080 - -/* -// Definitions of the bit fields in the HwPortB register for the -// MP1000 board. -*/ -#define HwPortBL3Mode 0x00000001 -#define HwPortBL3Clk 0x00000002 -#define HwPortBSClk 0x00000001 -#define HwPortBSData 0x00000002 -#define HwPortBL3Data 0x00000004 -#define HwPortBMute 0x00000008 -#define HwPortBQD0 0x00000010 -#define HwPortBQD1 0x00000020 -#define HwPortBQD2 0x00000040 -#define HwPortBQD3 0x00000080 - -/* -// Definitions of the bit fields in the HwPortD register for the -// MP1000 board. -*/ -#define HwPortDLED1 0x00000001 -#define HwPortDLED2 0x00000002 -#define HwPortDLED3 0x00000004 -#define HwPortDLED4 0x00000008 -#define HwPortDLED5 0x00000010 -#define HwPortDEECS 0x00000020 -#define HwPortBRTS 0x00000040 -#define HwPortBRI 0x00000080 - - -/* -// Definitions of the bit fields in the HwPortE register for the -// MP1000 board. -*/ - -#define HwPortECLE 0x00000001 -#define HwPortESepromDOut 0x00000001 -#define HwPortEALE 0x00000002 -#define HwPortESepromDIn 0x00000002 -#define HwPortENANDCS 0x00000004 -#define HwPortESepromCLK 0x00000004 - -#endif // #if defined (CONFIG_MACH_MP1000) - #endif diff --git a/include/asm-arm/arch-clps711x/mp1000-seprom.h b/include/asm-arm/arch-clps711x/mp1000-seprom.h deleted file mode 100644 index 3e5566cf9666..000000000000 --- a/include/asm-arm/arch-clps711x/mp1000-seprom.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef MP1000_SEPROM_H -#define MP1000_SEPROM_H - -/* - * mp1000-seprom.h - * - * - * This file contains the Serial EEPROM definitions for the MP1000 board - * - * Copyright (C) 2005 Comdial Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define COMMAND_ERASE (0x1C0) -#define COMMAND_ERASE_ALL (0x120) -#define COMMAND_WRITE_DISABLE (0x100) -#define COMMAND_WRITE_ENABLE (0x130) -#define COMMAND_READ (0x180) -#define COMMAND_WRITE (0x140) -#define COMMAND_WRITE_ALL (0x110) - -// -// Serial EEPROM data format -// - -#define PACKED __attribute__ ((packed)) - -typedef struct _EEPROM { - union { - unsigned char eprom_byte_data[128]; - unsigned short eprom_short_data[64]; - struct { - unsigned char version PACKED; // EEPROM Version "1" for now - unsigned char box_id PACKED; // Box ID (Standalone, SOHO, embedded, etc) - unsigned char major_hw_version PACKED; // Major Hardware version (Hex) - unsigned char minor_hw_version PACKED; // Minor Hardware Version (Hex) - unsigned char mfg_id[3] PACKED; // Manufacturer ID (3 character Alphabetic) - unsigned char mfg_serial_number[10] PACKED; // Manufacturer Serial number - unsigned char mfg_date[3] PACKED; // Date of Mfg (Formatted YY:MM:DD) - unsigned char country PACKED; // Country of deployment - unsigned char mac_Address[6] PACKED; // MAC Address - unsigned char oem_string[20] PACKED; // OEM ID string - unsigned short feature_bits1 PACKED; // Feature Bits 1 - unsigned short feature_bits2 PACKED; // Feature Bits 2 - unsigned char filler[75] PACKED; // Unused/Undefined “0” initialized - unsigned short checksum PACKED; // byte accumulated short checksum - } eprom_struct; - } variant; -} eeprom_struct; - -/* These settings must be mutually exclusive */ -#define FEATURE_BITS1_DRAMSIZE_16MEG 0x0001 /* 0 signifies 4 MEG system */ -#define FEATURE_BITS1_DRAMSIZE_8MEG 0x0002 /* 1 in bit 1 = 8MEG system */ -#define FEATURE_BITS1_DRAMSIZE_64MEG 0x0004 /* 1 in bit 2 = 64MEG system */ - -#define FEATURE_BITS1_CPUIS90MEG 0x0010 - -extern void seprom_init(void); -extern eeprom_struct* get_seprom_ptr(void); -extern unsigned char* get_eeprom_mac_address(void); - -#endif /* MP1000_SEPROM_H */ - -- cgit v1.2.3 From d530838bfa507d67b40d13b00d9cbd7a46a47e78 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 4 Nov 2005 15:33:38 -0500 Subject: NFSv4: Fix problem with OPEN_DOWNGRADE RFC 3530 states that for OPEN_DOWNGRADE "The share_access and share_deny bits specified must be exactly equal to the union of the share_access and share_deny bits specified for some subset of the OPENs in effect for current openowner on the current file. Setattr is currently violating the NFSv4 rules for OPEN_DOWNGRADE in that it may cause a downgrade from OPEN4_SHARE_ACCESS_BOTH to OPEN4_SHARE_ACCESS_WRITE despite the fact that there exists no open file with O_WRONLY access mode. Fix the problem by replacing nfs4_find_state() with a modified version of nfs_find_open_context(). Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 7 ++++++- fs/nfs/nfs4_fs.h | 1 - fs/nfs/nfs4proc.c | 23 ++++++++++------------- fs/nfs/nfs4state.c | 33 --------------------------------- fs/nfs/read.c | 4 ++-- fs/nfs/write.c | 2 +- include/linux/nfs_fs.h | 2 +- 7 files changed, 20 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index fc0f12ba89cc..24d2fbf549bd 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1009,13 +1009,18 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) spin_unlock(&inode->i_lock); } -struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode) +/* + * Given an inode, search for an open context with the desired characteristics + */ +struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *pos, *ctx = NULL; spin_lock(&inode->i_lock); list_for_each_entry(pos, &nfsi->open_files, list) { + if (cred != NULL && pos->cred != cred) + continue; if ((pos->mode & mode) == mode) { ctx = get_nfs_open_context(pos); break; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 53969022d239..b7f262dcb6e3 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -247,7 +247,6 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner *); extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct nfs4_state *, mode_t); -extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); extern void nfs4_schedule_state_recovery(struct nfs4_client *); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 02fddd0e27e8..9e492c2261c0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -214,7 +214,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, struct inode *inode = state->inode; open_flags &= (FMODE_READ|FMODE_WRITE); - /* Protect against nfs4_find_state() */ + /* Protect against nfs4_find_state_byowner() */ spin_lock(&state->owner->so_lock); spin_lock(&inode->i_lock); memcpy(&state->stateid, stateid, sizeof(state->stateid)); @@ -1274,7 +1274,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, { struct rpc_cred *cred; struct inode *inode = dentry->d_inode; - struct nfs4_state *state; + struct nfs_open_context *ctx; + struct nfs4_state *state = NULL; int status; nfs_fattr_init(fattr); @@ -1282,22 +1283,18 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); if (IS_ERR(cred)) return PTR_ERR(cred); - /* Search for an existing WRITE delegation first */ - state = nfs4_open_delegated(inode, FMODE_WRITE, cred); - if (!IS_ERR(state)) { - /* NB: nfs4_open_delegated() bumps the inode->i_count */ - iput(inode); - } else { - /* Search for an existing open(O_WRITE) stateid */ - state = nfs4_find_state(inode, cred, FMODE_WRITE); - } + + /* Search for an existing open(O_WRITE) file */ + ctx = nfs_find_open_context(inode, cred, FMODE_WRITE); + if (ctx != NULL) + state = ctx->state; status = nfs4_do_setattr(NFS_SERVER(inode), fattr, NFS_FH(inode), sattr, state); if (status == 0) nfs_setattr_update_inode(inode, sattr); - if (state != NULL) - nfs4_close_state(state, FMODE_WRITE); + if (ctx != NULL) + put_nfs_open_context(ctx); put_rpccred(cred); return status; } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 959374d833a7..81d964bfd8a7 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -383,28 +383,6 @@ nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode) state->state = mode; } -static struct nfs4_state * -__nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) -{ - struct nfs_inode *nfsi = NFS_I(inode); - struct nfs4_state *state; - - mode &= (FMODE_READ|FMODE_WRITE); - list_for_each_entry(state, &nfsi->open_states, inode_states) { - if (state->owner->so_cred != cred) - continue; - if ((state->state & mode) != mode) - continue; - atomic_inc(&state->count); - if (mode & FMODE_READ) - state->nreaders++; - if (mode & FMODE_WRITE) - state->nwriters++; - return state; - } - return NULL; -} - static struct nfs4_state * __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) { @@ -423,17 +401,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) return NULL; } -struct nfs4_state * -nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) -{ - struct nfs4_state *state; - - spin_lock(&inode->i_lock); - state = __nfs4_find_state(inode, cred, mode); - spin_unlock(&inode->i_lock); - return state; -} - static void nfs4_free_open_state(struct nfs4_state *state) { diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 43b03b19731b..5f20eafba8ec 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -507,7 +507,7 @@ int nfs_readpage(struct file *file, struct page *page) goto out_error; if (file == NULL) { - ctx = nfs_find_open_context(inode, FMODE_READ); + ctx = nfs_find_open_context(inode, NULL, FMODE_READ); if (ctx == NULL) return -EBADF; } else @@ -576,7 +576,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, nr_pages); if (filp == NULL) { - desc.ctx = nfs_find_open_context(inode, FMODE_READ); + desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); if (desc.ctx == NULL) return -EBADF; } else diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 819a65f5071f..1bdbd4f9fdd2 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -294,7 +294,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) if (page->index >= end_index+1 || !offset) goto out; do_it: - ctx = nfs_find_open_context(inode, FMODE_WRITE); + ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); if (ctx == NULL) { err = -EBADF; goto out; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 325fe7ae49bb..12787a9b0259 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -316,7 +316,7 @@ extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, st extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); extern void put_nfs_open_context(struct nfs_open_context *ctx); extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); -extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode); +extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode); extern void nfs_file_clear_open_context(struct file *filp); /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ -- cgit v1.2.3 From 5ad570786158e327a1c5d32dd3d66f26d8de6340 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 5 Nov 2005 10:33:55 +1100 Subject: powerpc: Merge smp.c and smp.h This also moves setup_cpu_maps to setup-common.c (calling it smp_setup_cpu_maps) and uses it on both 32-bit and 64-bit. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 4 +- arch/powerpc/kernel/setup-common.c | 119 +++++++- arch/powerpc/kernel/setup_32.c | 2 + arch/powerpc/kernel/setup_64.c | 120 +------- arch/powerpc/kernel/smp.c | 565 ++++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/chrp/smp.c | 39 +-- arch/ppc/kernel/Makefile | 1 - arch/ppc/kernel/irq.c | 2 +- arch/ppc64/kernel/Makefile | 1 - arch/ppc64/kernel/smp.c | 568 ------------------------------------- include/asm-powerpc/smp.h | 119 ++++++++ include/asm-ppc64/smp.h | 92 ------ 12 files changed, 812 insertions(+), 820 deletions(-) create mode 100644 arch/powerpc/kernel/smp.c delete mode 100644 arch/ppc64/kernel/smp.c create mode 100644 include/asm-powerpc/smp.h delete mode 100644 include/asm-ppc64/smp.h (limited to 'include') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 631149ea93db..b3ae2993efb8 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_PPC_OF) += prom_init.o obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_6xx) += idle_6xx.o +obj-$(CONFIG_SMP) += smp.o ifeq ($(CONFIG_PPC_ISERIES),y) $(obj)/head_64.o: $(obj)/lparmap.s @@ -49,8 +50,9 @@ endif else # stuff used from here for ARCH=ppc or ARCH=ppc64 +smpobj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o \ - setup-common.o + setup-common.o $(smpobj-y) endif diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 14ebe3bc48c3..d43fa8c0e5ac 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -170,11 +170,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) } #ifdef CONFIG_SMP -#ifdef CONFIG_PPC64 /* XXX for now */ pvr = per_cpu(pvr, cpu_id); -#else - pvr = cpu_data[cpu_id].pvr; -#endif #else pvr = mfspr(SPRN_PVR); #endif @@ -408,3 +404,118 @@ static int __init set_preferred_console(void) } console_initcall(set_preferred_console); #endif /* CONFIG_PPC_MULTIPLATFORM */ + +#ifdef CONFIG_SMP + +/** + * setup_cpu_maps - initialize the following cpu maps: + * cpu_possible_map + * cpu_present_map + * cpu_sibling_map + * + * Having the possible map set up early allows us to restrict allocations + * of things like irqstacks to num_possible_cpus() rather than NR_CPUS. + * + * We do not initialize the online map here; cpus set their own bits in + * cpu_online_map as they come up. + * + * This function is valid only for Open Firmware systems. finish_device_tree + * must be called before using this. + * + * While we're here, we may as well set the "physical" cpu ids in the paca. + */ +void __init smp_setup_cpu_maps(void) +{ + struct device_node *dn = NULL; + int cpu = 0; + int swap_cpuid = 0; + + while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { + int *intserv; + int j, len = sizeof(u32), nthreads = 1; + + intserv = (int *)get_property(dn, "ibm,ppc-interrupt-server#s", + &len); + if (intserv) + nthreads = len / sizeof(int); + else { + intserv = (int *) get_property(dn, "reg", NULL); + if (!intserv) + intserv = &cpu; /* assume logical == phys */ + } + + for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { + cpu_set(cpu, cpu_present_map); + set_hard_smp_processor_id(cpu, intserv[j]); + + if (intserv[j] == boot_cpuid_phys) + swap_cpuid = cpu; + cpu_set(cpu, cpu_possible_map); + cpu++; + } + } + + /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that + * boot cpu is logical 0. + */ + if (boot_cpuid_phys != get_hard_smp_processor_id(0)) { + u32 tmp; + tmp = get_hard_smp_processor_id(0); + set_hard_smp_processor_id(0, boot_cpuid_phys); + set_hard_smp_processor_id(swap_cpuid, tmp); + } + +#ifdef CONFIG_PPC64 + /* + * On pSeries LPAR, we need to know how many cpus + * could possibly be added to this partition. + */ + if (systemcfg->platform == PLATFORM_PSERIES_LPAR && + (dn = of_find_node_by_path("/rtas"))) { + int num_addr_cell, num_size_cell, maxcpus; + unsigned int *ireg; + + num_addr_cell = prom_n_addr_cells(dn); + num_size_cell = prom_n_size_cells(dn); + + ireg = (unsigned int *) + get_property(dn, "ibm,lrdr-capacity", NULL); + + if (!ireg) + goto out; + + maxcpus = ireg[num_addr_cell + num_size_cell]; + + /* Double maxcpus for processors which have SMT capability */ + if (cpu_has_feature(CPU_FTR_SMT)) + maxcpus *= 2; + + if (maxcpus > NR_CPUS) { + printk(KERN_WARNING + "Partition configured for %d cpus, " + "operating system maximum is %d.\n", + maxcpus, NR_CPUS); + maxcpus = NR_CPUS; + } else + printk(KERN_INFO "Partition configured for %d cpus.\n", + maxcpus); + + for (cpu = 0; cpu < maxcpus; cpu++) + cpu_set(cpu, cpu_possible_map); + out: + of_node_put(dn); + } + + /* + * Do the sibling map; assume only two threads per processor. + */ + for_each_cpu(cpu) { + cpu_set(cpu, cpu_sibling_map[cpu]); + if (cpu_has_feature(CPU_FTR_SMT)) + cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); + } + + systemcfg->processorCount = num_present_cpus(); +#endif /* CONFIG_PPC64 */ +} +#endif /* CONFIG_SMP */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 9680ae99b084..b45eedbb4b3a 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -288,6 +288,8 @@ void __init setup_arch(char **cmdline_p) unflatten_device_tree(); finish_device_tree(); + smp_setup_cpu_maps(); + #ifdef CONFIG_BOOTX_TEXT init_boot_display(); #endif diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 275d86ddd612..6b52cce872be 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -181,114 +181,8 @@ static int __init early_smt_enabled(char *p) } early_param("smt-enabled", early_smt_enabled); -/** - * setup_cpu_maps - initialize the following cpu maps: - * cpu_possible_map - * cpu_present_map - * cpu_sibling_map - * - * Having the possible map set up early allows us to restrict allocations - * of things like irqstacks to num_possible_cpus() rather than NR_CPUS. - * - * We do not initialize the online map here; cpus set their own bits in - * cpu_online_map as they come up. - * - * This function is valid only for Open Firmware systems. finish_device_tree - * must be called before using this. - * - * While we're here, we may as well set the "physical" cpu ids in the paca. - */ -static void __init setup_cpu_maps(void) -{ - struct device_node *dn = NULL; - int cpu = 0; - int swap_cpuid = 0; - - check_smt_enabled(); - - while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { - u32 *intserv; - int j, len = sizeof(u32), nthreads; - - intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s", - &len); - if (!intserv) - intserv = (u32 *)get_property(dn, "reg", NULL); - - nthreads = len / sizeof(u32); - - for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { - cpu_set(cpu, cpu_present_map); - set_hard_smp_processor_id(cpu, intserv[j]); - - if (intserv[j] == boot_cpuid_phys) - swap_cpuid = cpu; - cpu_set(cpu, cpu_possible_map); - cpu++; - } - } - - /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that - * boot cpu is logical 0. - */ - if (boot_cpuid_phys != get_hard_smp_processor_id(0)) { - u32 tmp; - tmp = get_hard_smp_processor_id(0); - set_hard_smp_processor_id(0, boot_cpuid_phys); - set_hard_smp_processor_id(swap_cpuid, tmp); - } - - /* - * On pSeries LPAR, we need to know how many cpus - * could possibly be added to this partition. - */ - if (systemcfg->platform == PLATFORM_PSERIES_LPAR && - (dn = of_find_node_by_path("/rtas"))) { - int num_addr_cell, num_size_cell, maxcpus; - unsigned int *ireg; - - num_addr_cell = prom_n_addr_cells(dn); - num_size_cell = prom_n_size_cells(dn); - - ireg = (unsigned int *) - get_property(dn, "ibm,lrdr-capacity", NULL); - - if (!ireg) - goto out; - - maxcpus = ireg[num_addr_cell + num_size_cell]; - - /* Double maxcpus for processors which have SMT capability */ - if (cpu_has_feature(CPU_FTR_SMT)) - maxcpus *= 2; - - if (maxcpus > NR_CPUS) { - printk(KERN_WARNING - "Partition configured for %d cpus, " - "operating system maximum is %d.\n", - maxcpus, NR_CPUS); - maxcpus = NR_CPUS; - } else - printk(KERN_INFO "Partition configured for %d cpus.\n", - maxcpus); - - for (cpu = 0; cpu < maxcpus; cpu++) - cpu_set(cpu, cpu_possible_map); - out: - of_node_put(dn); - } - - /* - * Do the sibling map; assume only two threads per processor. - */ - for_each_cpu(cpu) { - cpu_set(cpu, cpu_sibling_map[cpu]); - if (cpu_has_feature(CPU_FTR_SMT)) - cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); - } - - systemcfg->processorCount = num_present_cpus(); -} +#else +#define check_smt_enabled() #endif /* CONFIG_SMP */ extern struct machdep_calls pSeries_md; @@ -417,6 +311,8 @@ void smp_release_cpus(void) DBG(" <- smp_release_cpus()\n"); } +#else +#define smp_release_cpus() #endif /* CONFIG_SMP || CONFIG_KEXEC */ /* @@ -608,17 +504,13 @@ void __init setup_system(void) parse_early_param(); -#ifdef CONFIG_SMP - /* - * iSeries has already initialized the cpu maps at this point. - */ - setup_cpu_maps(); + check_smt_enabled(); + smp_setup_cpu_maps(); /* Release secondary cpus out of their spinloops at 0x60 now that * we can map physical -> logical CPU ids */ smp_release_cpus(); -#endif printk("Starting Linux PPC64 %s\n", system_utsname.version); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c new file mode 100644 index 000000000000..1794a694a928 --- /dev/null +++ b/arch/powerpc/kernel/smp.c @@ -0,0 +1,565 @@ +/* + * SMP support for ppc. + * + * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great + * deal of code from the sparc and intel versions. + * + * Copyright (C) 1999 Cort Dougan + * + * PowerPC-64 Support added by Dave Engebretsen, Peter Bergner, and + * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com + * + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PPC64 +#include +#endif + +int smp_hw_index[NR_CPUS]; +struct thread_info *secondary_ti; + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +cpumask_t cpu_possible_map = CPU_MASK_NONE; +cpumask_t cpu_online_map = CPU_MASK_NONE; +cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; + +EXPORT_SYMBOL(cpu_online_map); +EXPORT_SYMBOL(cpu_possible_map); + +/* SMP operations for this machine */ +struct smp_ops_t *smp_ops; + +static volatile unsigned int cpu_callin_map[NR_CPUS]; + +void smp_call_function_interrupt(void); + +int smt_enabled_at_boot = 1; + +#ifdef CONFIG_MPIC +int __init smp_mpic_probe(void) +{ + int nr_cpus; + + DBG("smp_mpic_probe()...\n"); + + nr_cpus = cpus_weight(cpu_possible_map); + + DBG("nr_cpus: %d\n", nr_cpus); + + if (nr_cpus > 1) + mpic_request_ipis(); + + return nr_cpus; +} + +void __devinit smp_mpic_setup_cpu(int cpu) +{ + mpic_setup_this_cpu(); +} +#endif /* CONFIG_MPIC */ + +#ifdef CONFIG_PPC64 +void __devinit smp_generic_kick_cpu(int nr) +{ + BUG_ON(nr < 0 || nr >= NR_CPUS); + + /* + * The processor is currently spinning, waiting for the + * cpu_start field to become non-zero After we set cpu_start, + * the processor will continue on to secondary_start + */ + paca[nr].cpu_start = 1; + smp_mb(); +} +#endif + +void smp_message_recv(int msg, struct pt_regs *regs) +{ + switch(msg) { + case PPC_MSG_CALL_FUNCTION: + smp_call_function_interrupt(); + break; + case PPC_MSG_RESCHEDULE: + /* XXX Do we have to do this? */ + set_need_resched(); + break; +#ifdef CONFIG_DEBUGGER + case PPC_MSG_DEBUGGER_BREAK: + debugger_ipi(regs); + break; +#endif + default: + printk("SMP %d: smp_message_recv(): unknown msg %d\n", + smp_processor_id(), msg); + break; + } +} + +void smp_send_reschedule(int cpu) +{ + smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE); +} + +#ifdef CONFIG_DEBUGGER +void smp_send_debugger_break(int cpu) +{ + smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK); +} +#endif + +static void stop_this_cpu(void *dummy) +{ + local_irq_disable(); + while (1) + ; +} + +void smp_send_stop(void) +{ + smp_call_function(stop_this_cpu, NULL, 1, 0); +} + +/* + * Structure and data for smp_call_function(). This is designed to minimise + * static memory requirements. It also looks cleaner. + * Stolen from the i386 version. + */ +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock); + +static struct call_data_struct { + void (*func) (void *info); + void *info; + atomic_t started; + atomic_t finished; + int wait; +} *call_data; + +/* delay of at least 8 seconds */ +#define SMP_CALL_TIMEOUT 8 + +/* + * This function sends a 'generic call function' IPI to all other CPUs + * in the system. + * + * [SUMMARY] Run a function on all other CPUs. + * The function to run. This must be fast and non-blocking. + * An arbitrary pointer to pass to the function. + * currently unused. + * If true, wait (atomically) until function has completed on other CPUs. + * [RETURNS] 0 on success, else a negative status code. Does not return until + * remote CPUs are nearly ready to execute <> or are or have executed. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. + */ +int smp_call_function (void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + struct call_data_struct data; + int ret = -1, cpus; + u64 timeout; + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + + data.func = func; + data.info = info; + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); + + spin_lock(&call_lock); + /* Must grab online cpu count with preempt disabled, otherwise + * it can change. */ + cpus = num_online_cpus() - 1; + if (!cpus) { + ret = 0; + goto out; + } + + call_data = &data; + smp_wmb(); + /* Send a message to all other CPUs and wait for them to respond */ + smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); + + timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec; + + /* Wait for response */ + while (atomic_read(&data.started) != cpus) { + HMT_low(); + if (get_tb() >= timeout) { + printk("smp_call_function on cpu %d: other cpus not " + "responding (%d)\n", smp_processor_id(), + atomic_read(&data.started)); + debugger(NULL); + goto out; + } + } + + if (wait) { + while (atomic_read(&data.finished) != cpus) { + HMT_low(); + if (get_tb() >= timeout) { + printk("smp_call_function on cpu %d: other " + "cpus not finishing (%d/%d)\n", + smp_processor_id(), + atomic_read(&data.finished), + atomic_read(&data.started)); + debugger(NULL); + goto out; + } + } + } + + ret = 0; + + out: + call_data = NULL; + HMT_medium(); + spin_unlock(&call_lock); + return ret; +} + +EXPORT_SYMBOL(smp_call_function); + +void smp_call_function_interrupt(void) +{ + void (*func) (void *info); + void *info; + int wait; + + /* call_data will be NULL if the sender timed out while + * waiting on us to receive the call. + */ + if (!call_data) + return; + + func = call_data->func; + info = call_data->info; + wait = call_data->wait; + + if (!wait) + smp_mb__before_atomic_inc(); + + /* + * Notify initiating CPU that I've grabbed the data and am + * about to execute the function + */ + atomic_inc(&call_data->started); + /* + * At this point the info structure may be out of scope unless wait==1 + */ + (*func)(info); + if (wait) { + smp_mb__before_atomic_inc(); + atomic_inc(&call_data->finished); + } +} + +extern struct gettimeofday_struct do_gtod; + +struct thread_info *current_set[NR_CPUS]; + +DECLARE_PER_CPU(unsigned int, pvr); + +static void __devinit smp_store_cpu_info(int id) +{ + per_cpu(pvr, id) = mfspr(SPRN_PVR); +} + +static void __init smp_create_idle(unsigned int cpu) +{ + struct task_struct *p; + + /* create a process for the processor */ + p = fork_idle(cpu); + if (IS_ERR(p)) + panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); +#ifdef CONFIG_PPC64 + paca[cpu].__current = p; +#endif + current_set[cpu] = p->thread_info; + p->thread_info->cpu = cpu; +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int cpu; + + DBG("smp_prepare_cpus\n"); + + /* + * setup_cpu may need to be called on the boot cpu. We havent + * spun any cpus up but lets be paranoid. + */ + BUG_ON(boot_cpuid != smp_processor_id()); + + /* Fixup boot cpu */ + smp_store_cpu_info(boot_cpuid); + cpu_callin_map[boot_cpuid] = 1; + + max_cpus = smp_ops->probe(); + + smp_space_timers(max_cpus); + + for_each_cpu(cpu) + if (cpu != boot_cpuid) + smp_create_idle(cpu); +} + +void __devinit smp_prepare_boot_cpu(void) +{ + BUG_ON(smp_processor_id() != boot_cpuid); + + cpu_set(boot_cpuid, cpu_online_map); +#ifdef CONFIG_PPC64 + paca[boot_cpuid].__current = current; +#endif + current_set[boot_cpuid] = current->thread_info; +} + +#ifdef CONFIG_HOTPLUG_CPU +/* State of each CPU during hotplug phases */ +DEFINE_PER_CPU(int, cpu_state) = { 0 }; + +int generic_cpu_disable(void) +{ + unsigned int cpu = smp_processor_id(); + + if (cpu == boot_cpuid) + return -EBUSY; + + systemcfg->processorCount--; + cpu_clear(cpu, cpu_online_map); + fixup_irqs(cpu_online_map); + return 0; +} + +int generic_cpu_enable(unsigned int cpu) +{ + /* Do the normal bootup if we haven't + * already bootstrapped. */ + if (system_state != SYSTEM_RUNNING) + return -ENOSYS; + + /* get the target out of it's holding state */ + per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; + smp_wmb(); + + while (!cpu_online(cpu)) + cpu_relax(); + + fixup_irqs(cpu_online_map); + /* counter the irq disable in fixup_irqs */ + local_irq_enable(); + return 0; +} + +void generic_cpu_die(unsigned int cpu) +{ + int i; + + for (i = 0; i < 100; i++) { + smp_rmb(); + if (per_cpu(cpu_state, cpu) == CPU_DEAD) + return; + msleep(100); + } + printk(KERN_ERR "CPU%d didn't die...\n", cpu); +} + +void generic_mach_cpu_die(void) +{ + unsigned int cpu; + + local_irq_disable(); + cpu = smp_processor_id(); + printk(KERN_DEBUG "CPU%d offline\n", cpu); + __get_cpu_var(cpu_state) = CPU_DEAD; + smp_wmb(); + while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) + cpu_relax(); + + flush_tlb_pending(); + cpu_set(cpu, cpu_online_map); + local_irq_enable(); +} +#endif + +static int __devinit cpu_enable(unsigned int cpu) +{ + if (smp_ops->cpu_enable) + return smp_ops->cpu_enable(cpu); + + return -ENOSYS; +} + +int __devinit __cpu_up(unsigned int cpu) +{ + int c; + + secondary_ti = current_set[cpu]; + if (!cpu_enable(cpu)) + return 0; + + if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) + return -EINVAL; + +#ifdef CONFIG_PPC64 + paca[cpu].default_decr = tb_ticks_per_jiffy; +#endif + + /* Make sure callin-map entry is 0 (can be leftover a CPU + * hotplug + */ + cpu_callin_map[cpu] = 0; + + /* The information for processor bringup must + * be written out to main store before we release + * the processor. + */ + smp_mb(); + + /* wake up cpus */ + DBG("smp: kicking cpu %d\n", cpu); + smp_ops->kick_cpu(cpu); + + /* + * wait to see if the cpu made a callin (is actually up). + * use this value that I found through experimentation. + * -- Cort + */ + if (system_state < SYSTEM_RUNNING) + for (c = 5000; c && !cpu_callin_map[cpu]; c--) + udelay(100); +#ifdef CONFIG_HOTPLUG_CPU + else + /* + * CPUs can take much longer to come up in the + * hotplug case. Wait five seconds. + */ + for (c = 25; c && !cpu_callin_map[cpu]; c--) { + msleep(200); + } +#endif + + if (!cpu_callin_map[cpu]) { + printk("Processor %u is stuck.\n", cpu); + return -ENOENT; + } + + printk("Processor %u found.\n", cpu); + + if (smp_ops->give_timebase) + smp_ops->give_timebase(); + + /* Wait until cpu puts itself in the online map */ + while (!cpu_online(cpu)) + cpu_relax(); + + return 0; +} + + +/* Activate a secondary processor. */ +int __devinit start_secondary(void *unused) +{ + unsigned int cpu = smp_processor_id(); + + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + + smp_store_cpu_info(cpu); + set_dec(tb_ticks_per_jiffy); + cpu_callin_map[cpu] = 1; + + smp_ops->setup_cpu(cpu); + if (smp_ops->take_timebase) + smp_ops->take_timebase(); + + spin_lock(&call_lock); + cpu_set(cpu, cpu_online_map); + spin_unlock(&call_lock); + + local_irq_enable(); + + cpu_idle(); + return 0; +} + +int setup_profiling_timer(unsigned int multiplier) +{ + return 0; +} + +void __init smp_cpus_done(unsigned int max_cpus) +{ + cpumask_t old_mask; + + /* We want the setup_cpu() here to be called from CPU 0, but our + * init thread may have been "borrowed" by another CPU in the meantime + * se we pin us down to CPU 0 for a short while + */ + old_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); + + smp_ops->setup_cpu(boot_cpuid); + + set_cpus_allowed(current, old_mask); +} + +#ifdef CONFIG_HOTPLUG_CPU +int __cpu_disable(void) +{ + if (smp_ops->cpu_disable) + return smp_ops->cpu_disable(); + + return -ENOSYS; +} + +void __cpu_die(unsigned int cpu) +{ + if (smp_ops->cpu_die) + smp_ops->cpu_die(cpu); +} +#endif diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index 31ee49c25014..bb2315997d45 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c @@ -35,43 +35,6 @@ #include #include -extern unsigned long smp_chrp_cpu_nr; - -static int __init smp_chrp_probe(void) -{ - struct device_node *cpus = NULL; - unsigned int *reg; - int reglen; - int ncpus = 0; - int cpuid; - unsigned int phys; - - /* Count CPUs in the device-tree */ - cpuid = 1; /* the boot cpu is logical cpu 0 */ - while ((cpus = of_find_node_by_type(cpus, "cpu")) != NULL) { - phys = ncpus; - reg = (unsigned int *) get_property(cpus, "reg", ®len); - if (reg && reglen >= sizeof(unsigned int)) - /* hmmm, not having a reg property would be bad */ - phys = *reg; - if (phys != boot_cpuid_phys) { - set_hard_smp_processor_id(cpuid, phys); - ++cpuid; - } - ++ncpus; - } - - printk(KERN_INFO "CHRP SMP probe found %d cpus\n", ncpus); - - /* Nothing more to do if less than 2 of them */ - if (ncpus <= 1) - return 1; - - mpic_request_ipis(); - - return ncpus; -} - static void __devinit smp_chrp_kick_cpu(int nr) { *(unsigned long *)KERNELBASE = nr; @@ -114,7 +77,7 @@ void __devinit smp_chrp_take_timebase(void) /* CHRP with openpic */ struct smp_ops_t chrp_smp_ops = { .message_pass = smp_mpic_message_pass, - .probe = smp_chrp_probe, + .probe = smp_mpic_probe, .kick_cpu = smp_chrp_kick_cpu, .setup_cpu = smp_chrp_setup_cpu, .give_timebase = smp_chrp_give_timebase, diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index b35346df1e37..c610ca933a25 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_KGDB) += ppc-stub.o -obj-$(CONFIG_SMP) += smp.o smp-tbsync.o obj-$(CONFIG_TAU) += temp.o ifndef CONFIG_E200 obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index 772e428aaa59..fbb2b9f8922c 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -126,7 +126,7 @@ skip: seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); } #endif -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) /* should this be per processor send/receive? */ seq_printf(p, "IPI (recv/sent): %10u/%u\n", atomic_read(&ipi_recv), atomic_read(&ipi_sent)); diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index f597c2954b71..c441aebe7648 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o obj-$(CONFIG_KEXEC) += machine_kexec.o obj-$(CONFIG_EEH) += eeh.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o -obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ifneq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_MODULES) += ppc_ksyms.o diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c deleted file mode 100644 index 017c12919832..000000000000 --- a/arch/ppc64/kernel/smp.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * SMP support for ppc. - * - * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great - * deal of code from the sparc and intel versions. - * - * Copyright (C) 1999 Cort Dougan - * - * PowerPC-64 Support added by Dave Engebretsen, Peter Bergner, and - * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com - * - * 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. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -#define DBG(fmt...) udbg_printf(fmt) -#else -#define DBG(fmt...) -#endif - -cpumask_t cpu_possible_map = CPU_MASK_NONE; -cpumask_t cpu_online_map = CPU_MASK_NONE; -cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; - -EXPORT_SYMBOL(cpu_online_map); -EXPORT_SYMBOL(cpu_possible_map); - -struct smp_ops_t *smp_ops; - -static volatile unsigned int cpu_callin_map[NR_CPUS]; - -void smp_call_function_interrupt(void); - -int smt_enabled_at_boot = 1; - -#ifdef CONFIG_MPIC -int __init smp_mpic_probe(void) -{ - int nr_cpus; - - DBG("smp_mpic_probe()...\n"); - - nr_cpus = cpus_weight(cpu_possible_map); - - DBG("nr_cpus: %d\n", nr_cpus); - - if (nr_cpus > 1) - mpic_request_ipis(); - - return nr_cpus; -} - -void __devinit smp_mpic_setup_cpu(int cpu) -{ - mpic_setup_this_cpu(); -} - -void __devinit smp_generic_kick_cpu(int nr) -{ - BUG_ON(nr < 0 || nr >= NR_CPUS); - - /* - * The processor is currently spinning, waiting for the - * cpu_start field to become non-zero After we set cpu_start, - * the processor will continue on to secondary_start - */ - paca[nr].cpu_start = 1; - smp_mb(); -} - -#endif /* CONFIG_MPIC */ - -void smp_message_recv(int msg, struct pt_regs *regs) -{ - switch(msg) { - case PPC_MSG_CALL_FUNCTION: - smp_call_function_interrupt(); - break; - case PPC_MSG_RESCHEDULE: - /* XXX Do we have to do this? */ - set_need_resched(); - break; -#if 0 - case PPC_MSG_MIGRATE_TASK: - /* spare */ - break; -#endif -#ifdef CONFIG_DEBUGGER - case PPC_MSG_DEBUGGER_BREAK: - debugger_ipi(regs); - break; -#endif - default: - printk("SMP %d: smp_message_recv(): unknown msg %d\n", - smp_processor_id(), msg); - break; - } -} - -void smp_send_reschedule(int cpu) -{ - smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE); -} - -#ifdef CONFIG_DEBUGGER -void smp_send_debugger_break(int cpu) -{ - smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK); -} -#endif - -static void stop_this_cpu(void *dummy) -{ - local_irq_disable(); - while (1) - ; -} - -void smp_send_stop(void) -{ - smp_call_function(stop_this_cpu, NULL, 1, 0); -} - -/* - * Structure and data for smp_call_function(). This is designed to minimise - * static memory requirements. It also looks cleaner. - * Stolen from the i386 version. - */ -static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock); - -static struct call_data_struct { - void (*func) (void *info); - void *info; - atomic_t started; - atomic_t finished; - int wait; -} *call_data; - -/* delay of at least 8 seconds on 1GHz cpu */ -#define SMP_CALL_TIMEOUT (1UL << (30 + 3)) - -/* - * This function sends a 'generic call function' IPI to all other CPUs - * in the system. - * - * [SUMMARY] Run a function on all other CPUs. - * The function to run. This must be fast and non-blocking. - * An arbitrary pointer to pass to the function. - * currently unused. - * If true, wait (atomically) until function has completed on other CPUs. - * [RETURNS] 0 on success, else a negative status code. Does not return until - * remote CPUs are nearly ready to execute <> or are or have executed. - * - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. - */ -int smp_call_function (void (*func) (void *info), void *info, int nonatomic, - int wait) -{ - struct call_data_struct data; - int ret = -1, cpus; - unsigned long timeout; - - /* Can deadlock when called with interrupts disabled */ - WARN_ON(irqs_disabled()); - - data.func = func; - data.info = info; - atomic_set(&data.started, 0); - data.wait = wait; - if (wait) - atomic_set(&data.finished, 0); - - spin_lock(&call_lock); - /* Must grab online cpu count with preempt disabled, otherwise - * it can change. */ - cpus = num_online_cpus() - 1; - if (!cpus) { - ret = 0; - goto out; - } - - call_data = &data; - smp_wmb(); - /* Send a message to all other CPUs and wait for them to respond */ - smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); - - /* Wait for response */ - timeout = SMP_CALL_TIMEOUT; - while (atomic_read(&data.started) != cpus) { - HMT_low(); - if (--timeout == 0) { - printk("smp_call_function on cpu %d: other cpus not " - "responding (%d)\n", smp_processor_id(), - atomic_read(&data.started)); - debugger(NULL); - goto out; - } - } - - if (wait) { - timeout = SMP_CALL_TIMEOUT; - while (atomic_read(&data.finished) != cpus) { - HMT_low(); - if (--timeout == 0) { - printk("smp_call_function on cpu %d: other " - "cpus not finishing (%d/%d)\n", - smp_processor_id(), - atomic_read(&data.finished), - atomic_read(&data.started)); - debugger(NULL); - goto out; - } - } - } - - ret = 0; - -out: - call_data = NULL; - HMT_medium(); - spin_unlock(&call_lock); - return ret; -} - -EXPORT_SYMBOL(smp_call_function); - -void smp_call_function_interrupt(void) -{ - void (*func) (void *info); - void *info; - int wait; - - /* call_data will be NULL if the sender timed out while - * waiting on us to receive the call. - */ - if (!call_data) - return; - - func = call_data->func; - info = call_data->info; - wait = call_data->wait; - - if (!wait) - smp_mb__before_atomic_inc(); - - /* - * Notify initiating CPU that I've grabbed the data and am - * about to execute the function - */ - atomic_inc(&call_data->started); - /* - * At this point the info structure may be out of scope unless wait==1 - */ - (*func)(info); - if (wait) { - smp_mb__before_atomic_inc(); - atomic_inc(&call_data->finished); - } -} - -extern struct gettimeofday_struct do_gtod; - -struct thread_info *current_set[NR_CPUS]; - -DECLARE_PER_CPU(unsigned int, pvr); - -static void __devinit smp_store_cpu_info(int id) -{ - per_cpu(pvr, id) = mfspr(SPRN_PVR); -} - -static void __init smp_create_idle(unsigned int cpu) -{ - struct task_struct *p; - - /* create a process for the processor */ - p = fork_idle(cpu); - if (IS_ERR(p)) - panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - paca[cpu].__current = p; - current_set[cpu] = p->thread_info; -} - -void __init smp_prepare_cpus(unsigned int max_cpus) -{ - unsigned int cpu; - - DBG("smp_prepare_cpus\n"); - - /* - * setup_cpu may need to be called on the boot cpu. We havent - * spun any cpus up but lets be paranoid. - */ - BUG_ON(boot_cpuid != smp_processor_id()); - - /* Fixup boot cpu */ - smp_store_cpu_info(boot_cpuid); - cpu_callin_map[boot_cpuid] = 1; - -#ifndef CONFIG_PPC_ISERIES - paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb(); - - /* - * Should update do_gtod.stamp_xsec. - * For now we leave it which means the time can be some - * number of msecs off until someone does a settimeofday() - */ - do_gtod.varp->tb_orig_stamp = tb_last_stamp; - systemcfg->tb_orig_stamp = tb_last_stamp; -#endif - - max_cpus = smp_ops->probe(); - - smp_space_timers(max_cpus); - - for_each_cpu(cpu) - if (cpu != boot_cpuid) - smp_create_idle(cpu); -} - -void __devinit smp_prepare_boot_cpu(void) -{ - BUG_ON(smp_processor_id() != boot_cpuid); - - cpu_set(boot_cpuid, cpu_online_map); - - paca[boot_cpuid].__current = current; - current_set[boot_cpuid] = current->thread_info; -} - -#ifdef CONFIG_HOTPLUG_CPU -/* State of each CPU during hotplug phases */ -DEFINE_PER_CPU(int, cpu_state) = { 0 }; - -int generic_cpu_disable(void) -{ - unsigned int cpu = smp_processor_id(); - - if (cpu == boot_cpuid) - return -EBUSY; - - systemcfg->processorCount--; - cpu_clear(cpu, cpu_online_map); - fixup_irqs(cpu_online_map); - return 0; -} - -int generic_cpu_enable(unsigned int cpu) -{ - /* Do the normal bootup if we haven't - * already bootstrapped. */ - if (system_state != SYSTEM_RUNNING) - return -ENOSYS; - - /* get the target out of it's holding state */ - per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; - smp_wmb(); - - while (!cpu_online(cpu)) - cpu_relax(); - - fixup_irqs(cpu_online_map); - /* counter the irq disable in fixup_irqs */ - local_irq_enable(); - return 0; -} - -void generic_cpu_die(unsigned int cpu) -{ - int i; - - for (i = 0; i < 100; i++) { - smp_rmb(); - if (per_cpu(cpu_state, cpu) == CPU_DEAD) - return; - msleep(100); - } - printk(KERN_ERR "CPU%d didn't die...\n", cpu); -} - -void generic_mach_cpu_die(void) -{ - unsigned int cpu; - - local_irq_disable(); - cpu = smp_processor_id(); - printk(KERN_DEBUG "CPU%d offline\n", cpu); - __get_cpu_var(cpu_state) = CPU_DEAD; - smp_wmb(); - while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) - cpu_relax(); - - flush_tlb_pending(); - cpu_set(cpu, cpu_online_map); - local_irq_enable(); -} -#endif - -static int __devinit cpu_enable(unsigned int cpu) -{ - if (smp_ops->cpu_enable) - return smp_ops->cpu_enable(cpu); - - return -ENOSYS; -} - -int __devinit __cpu_up(unsigned int cpu) -{ - int c; - - if (!cpu_enable(cpu)) - return 0; - - if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) - return -EINVAL; - - paca[cpu].default_decr = tb_ticks_per_jiffy; - - /* Make sure callin-map entry is 0 (can be leftover a CPU - * hotplug - */ - cpu_callin_map[cpu] = 0; - - /* The information for processor bringup must - * be written out to main store before we release - * the processor. - */ - smp_mb(); - - /* wake up cpus */ - DBG("smp: kicking cpu %d\n", cpu); - smp_ops->kick_cpu(cpu); - - /* - * wait to see if the cpu made a callin (is actually up). - * use this value that I found through experimentation. - * -- Cort - */ - if (system_state < SYSTEM_RUNNING) - for (c = 5000; c && !cpu_callin_map[cpu]; c--) - udelay(100); -#ifdef CONFIG_HOTPLUG_CPU - else - /* - * CPUs can take much longer to come up in the - * hotplug case. Wait five seconds. - */ - for (c = 25; c && !cpu_callin_map[cpu]; c--) { - msleep(200); - } -#endif - - if (!cpu_callin_map[cpu]) { - printk("Processor %u is stuck.\n", cpu); - return -ENOENT; - } - - printk("Processor %u found.\n", cpu); - - if (smp_ops->give_timebase) - smp_ops->give_timebase(); - - /* Wait until cpu puts itself in the online map */ - while (!cpu_online(cpu)) - cpu_relax(); - - return 0; -} - - -/* Activate a secondary processor. */ -int __devinit start_secondary(void *unused) -{ - unsigned int cpu = smp_processor_id(); - - atomic_inc(&init_mm.mm_count); - current->active_mm = &init_mm; - - smp_store_cpu_info(cpu); - set_dec(paca[cpu].default_decr); - cpu_callin_map[cpu] = 1; - - smp_ops->setup_cpu(cpu); - if (smp_ops->take_timebase) - smp_ops->take_timebase(); - - spin_lock(&call_lock); - cpu_set(cpu, cpu_online_map); - spin_unlock(&call_lock); - - local_irq_enable(); - - cpu_idle(); - return 0; -} - -int setup_profiling_timer(unsigned int multiplier) -{ - return 0; -} - -void __init smp_cpus_done(unsigned int max_cpus) -{ - cpumask_t old_mask; - - /* We want the setup_cpu() here to be called from CPU 0, but our - * init thread may have been "borrowed" by another CPU in the meantime - * se we pin us down to CPU 0 for a short while - */ - old_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); - - smp_ops->setup_cpu(boot_cpuid); - - set_cpus_allowed(current, old_mask); -} - -#ifdef CONFIG_HOTPLUG_CPU -int __cpu_disable(void) -{ - if (smp_ops->cpu_disable) - return smp_ops->cpu_disable(); - - return -ENOSYS; -} - -void __cpu_die(unsigned int cpu) -{ - if (smp_ops->cpu_die) - smp_ops->cpu_die(cpu); -} -#endif diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h new file mode 100644 index 000000000000..8bcdd0faefea --- /dev/null +++ b/include/asm-powerpc/smp.h @@ -0,0 +1,119 @@ +/* + * smp.h: PowerPC-specific SMP code. + * + * Original was a copy of sparc smp.h. Now heavily modified + * for PPC. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996-2001 Cort Dougan + * + * 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. + */ + +#ifndef _ASM_POWERPC_SMP_H +#define _ASM_POWERPC_SMP_H +#ifdef __KERNEL__ + +#include +#include +#include +#include + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_PPC64 +#include +#endif + +extern int boot_cpuid; +extern int boot_cpuid_phys; + +extern void cpu_die(void); + +#ifdef CONFIG_SMP + +extern void smp_send_debugger_break(int cpu); +struct pt_regs; +extern void smp_message_recv(int, struct pt_regs *); + +#ifdef CONFIG_HOTPLUG_CPU +extern void fixup_irqs(cpumask_t map); +int generic_cpu_disable(void); +int generic_cpu_enable(unsigned int cpu); +void generic_cpu_die(unsigned int cpu); +void generic_mach_cpu_die(void); +#endif + +#ifdef CONFIG_PPC64 +#define raw_smp_processor_id() (get_paca()->paca_index) +#define hard_smp_processor_id() (get_paca()->hw_cpu_id) +#else +/* 32-bit */ +extern int smp_hw_index[]; + +#define raw_smp_processor_id() (current_thread_info()->cpu) +#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()]) +#define get_hard_smp_processor_id(cpu) (smp_hw_index[(cpu)]) +#define set_hard_smp_processor_id(cpu, phys)\ + (smp_hw_index[(cpu)] = (phys)) +#endif + +extern cpumask_t cpu_sibling_map[NR_CPUS]; + +/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. + * + * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up + * in /proc/interrupts will be wrong!!! --Troy */ +#define PPC_MSG_CALL_FUNCTION 0 +#define PPC_MSG_RESCHEDULE 1 +/* This is unused now */ +#if 0 +#define PPC_MSG_MIGRATE_TASK 2 +#endif +#define PPC_MSG_DEBUGGER_BREAK 3 + +void smp_init_iSeries(void); +void smp_init_pSeries(void); +void smp_init_cell(void); +void smp_setup_cpu_maps(void); + +extern int __cpu_disable(void); +extern void __cpu_die(unsigned int cpu); + +#else +/* for UP */ +#define smp_setup_cpu_maps() +#define smp_release_cpus() + +#endif /* CONFIG_SMP */ + +#ifdef CONFIG_PPC64 +#define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id) +#define set_hard_smp_processor_id(CPU, VAL) \ + do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0) +#else +/* 32-bit */ +#ifndef CONFIG_SMP +#define get_hard_smp_processor_id(cpu) boot_cpuid_phys +#define set_hard_smp_processor_id(cpu, phys) +#endif +#endif + +extern int smt_enabled_at_boot; + +extern int smp_mpic_probe(void); +extern void smp_mpic_setup_cpu(int cpu); +extern void smp_generic_kick_cpu(int nr); + +extern void smp_generic_give_timebase(void); +extern void smp_generic_take_timebase(void); + +extern struct smp_ops_t *smp_ops; + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_SMP_H) */ diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h deleted file mode 100644 index ba0f5c8bbb22..000000000000 --- a/include/asm-ppc64/smp.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * smp.h: PPC64 specific SMP code. - * - * Original was a copy of sparc smp.h. Now heavily modified - * for PPC. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996-2001 Cort Dougan - * - * 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. - */ - -#ifdef __KERNEL__ -#ifndef _PPC64_SMP_H -#define _PPC64_SMP_H - -#include -#include -#include -#include - -#ifndef __ASSEMBLY__ - -#include - -extern int boot_cpuid; -extern int boot_cpuid_phys; - -extern void cpu_die(void); - -#ifdef CONFIG_SMP - -extern void smp_send_debugger_break(int cpu); -struct pt_regs; -extern void smp_message_recv(int, struct pt_regs *); - -#ifdef CONFIG_HOTPLUG_CPU -extern void fixup_irqs(cpumask_t map); -int generic_cpu_disable(void); -int generic_cpu_enable(unsigned int cpu); -void generic_cpu_die(unsigned int cpu); -void generic_mach_cpu_die(void); -#endif - -#define raw_smp_processor_id() (get_paca()->paca_index) -#define hard_smp_processor_id() (get_paca()->hw_cpu_id) - -extern cpumask_t cpu_sibling_map[NR_CPUS]; - -/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. - * - * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up - * in /proc/interrupts will be wrong!!! --Troy */ -#define PPC_MSG_CALL_FUNCTION 0 -#define PPC_MSG_RESCHEDULE 1 -/* This is unused now */ -#if 0 -#define PPC_MSG_MIGRATE_TASK 2 -#endif -#define PPC_MSG_DEBUGGER_BREAK 3 - -void smp_init_iSeries(void); -void smp_init_pSeries(void); -void smp_init_cell(void); - -extern int __cpu_disable(void); -extern void __cpu_die(unsigned int cpu); -#endif /* CONFIG_SMP */ - -#define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id) -#define set_hard_smp_processor_id(CPU, VAL) \ - do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0) - -extern int smt_enabled_at_boot; - -extern int smp_mpic_probe(void); -extern void smp_mpic_setup_cpu(int cpu); -extern void smp_generic_kick_cpu(int nr); -extern void smp_release_cpus(void); - -extern void smp_generic_give_timebase(void); -extern void smp_generic_take_timebase(void); - -extern struct smp_ops_t *smp_ops; - -#endif /* __ASSEMBLY__ */ - -#endif /* !(_PPC64_SMP_H) */ -#endif /* __KERNEL__ */ -- cgit v1.2.3 From 7015faa7df829876a0f931cd18aa6d7c24a1b581 Mon Sep 17 00:00:00 2001 From: "Calin A. Culianu" Date: Fri, 4 Nov 2005 20:38:04 -0500 Subject: [PATCH] nvidiafb: Geforce 7800 series support added This adds support for the Nvidia Geforce 7800 series of cards to the nvidiafb framebuffer driver. All it does is add the PCI device id for the 7800, 7800 GTX, 7800 GO, and 7800 GTX GO cards to the module device table for the nvidiafb.ko driver, so that nvidiafb.ko will actually work on these cards. I also added the relevant PCI device ids to linux/pci_ids.h I tested it on my 7800 GTX here and it works like a charm. I now can get framebuffer support on this card! Woo hoo!! Nothing like 200x75 text mode to make your eyes BLEED. ;) Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nvidia.c | 8 ++++++++ include/linux/pci_ids.h | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'include') diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7f020ada630..308defc389a2 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -384,6 +384,14 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021e, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 56192005fa4d..88de3f8ce1a2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -990,6 +990,10 @@ #define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a #define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT 0x0090 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX 0x0091 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800 0x0098 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099 #define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 #define PCI_DEVICE_ID_GEFORCE_6800A 0x00c1 #define PCI_DEVICE_ID_GEFORCE_6800A_LE 0x00c2 -- cgit v1.2.3 From 6037d6bbdff65eb5a84fe35e140f4da4f7cc103a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 4 Nov 2005 22:08:00 -0500 Subject: [libata] ATAPI pad allocation fixes/cleanup Use ata_pad_{alloc,free} in two drivers, to factor out common code. Add ata_pad_{alloc,free} to two other drivers, which needed the padding but had not been updated. --- drivers/scsi/ahci.c | 11 ++++++----- drivers/scsi/libata-core.c | 9 +++++---- drivers/scsi/sata_mv.c | 31 +++++++++++++++++++++++-------- drivers/scsi/sata_sil24.c | 33 ++++++++++++++++++++++++--------- include/linux/libata.h | 13 +++++++++++++ 5 files changed, 71 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 8420204c2eaa..4612312c0c2d 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -307,21 +307,22 @@ static int ahci_port_start(struct ata_port *ap) void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void *mem; dma_addr_t mem_dma; + int rc; pp = kmalloc(sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; memset(pp, 0, sizeof(*pp)); - ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); - if (!ap->pad) { + rc = ata_pad_alloc(ap, dev); + if (rc) { kfree(pp); - return -ENOMEM; + return rc; } mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { - dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); + ata_pad_free(ap, dev); kfree(pp); return -ENOMEM; } @@ -397,7 +398,7 @@ static void ahci_port_stop(struct ata_port *ap) ap->private_data = NULL; dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, pp->cmd_slot, pp->cmd_slot_dma); - dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); + ata_pad_free(ap, dev); kfree(pp); } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ae2475e4291c..e1346cddd37f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4091,15 +4091,16 @@ err_out: int ata_port_start (struct ata_port *ap) { struct device *dev = ap->host_set->dev; + int rc; ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); if (!ap->prd) return -ENOMEM; - ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); - if (!ap->pad) { + rc = ata_pad_alloc(ap, dev); + if (rc) { dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); - return -ENOMEM; + return rc; } DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma); @@ -4125,7 +4126,7 @@ void ata_port_stop (struct ata_port *ap) struct device *dev = ap->host_set->dev; dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); - dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); + ata_pad_free(ap, dev); } void ata_host_stop (struct ata_host_set *host_set) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 64af334e71f4..0f469e3dabe2 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -670,6 +670,11 @@ static void mv_host_stop(struct ata_host_set *host_set) ata_host_stop(host_set); } +static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) +{ + dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); +} + /** * mv_port_start - Port specific init/start routine. * @ap: ATA channel to manipulate @@ -687,21 +692,23 @@ static int mv_port_start(struct ata_port *ap) void __iomem *port_mmio = mv_ap_base(ap); void *mem; dma_addr_t mem_dma; + int rc = -ENOMEM; pp = kmalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) { - return -ENOMEM; - } + if (!pp) + goto err_out; memset(pp, 0, sizeof(*pp)); mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); - if (!mem) { - kfree(pp); - return -ENOMEM; - } + if (!mem) + goto err_out_pp; memset(mem, 0, MV_PORT_PRIV_DMA_SZ); + rc = ata_pad_alloc(ap, dev); + if (rc) + goto err_out_priv; + /* First item in chunk of DMA memory: * 32-slot command request table (CRQB), 32 bytes each in size */ @@ -746,6 +753,13 @@ static int mv_port_start(struct ata_port *ap) */ ap->private_data = pp; return 0; + +err_out_priv: + mv_priv_free(pp, dev); +err_out_pp: + kfree(pp); +err_out: + return rc; } /** @@ -768,7 +782,8 @@ static void mv_port_stop(struct ata_port *ap) spin_unlock_irqrestore(&ap->host_set->lock, flags); ap->private_data = NULL; - dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); + ata_pad_free(ap, dev); + mv_priv_free(pp, dev); kfree(pp); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 211ec7eebc9c..e6c8e89c226f 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -635,6 +635,13 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * return IRQ_RETVAL(handled); } +static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) +{ + const size_t cb_size = sizeof(*pp->cmd_block); + + dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); +} + static int sil24_port_start(struct ata_port *ap) { struct device *dev = ap->host_set->dev; @@ -642,36 +649,44 @@ static int sil24_port_start(struct ata_port *ap) struct sil24_cmd_block *cb; size_t cb_size = sizeof(*cb); dma_addr_t cb_dma; + int rc = -ENOMEM; - pp = kmalloc(sizeof(*pp), GFP_KERNEL); + pp = kzalloc(sizeof(*pp), GFP_KERNEL); if (!pp) - return -ENOMEM; - memset(pp, 0, sizeof(*pp)); + goto err_out; pp->tf.command = ATA_DRDY; cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); - if (!cb) { - kfree(pp); - return -ENOMEM; - } + if (!cb) + goto err_out_pp; memset(cb, 0, cb_size); + rc = ata_pad_alloc(ap, dev); + if (rc) + goto err_out_pad; + pp->cmd_block = cb; pp->cmd_block_dma = cb_dma; ap->private_data = pp; return 0; + +err_out_pad: + sil24_cblk_free(pp, dev); +err_out_pp: + kfree(pp); +err_out: + return rc; } static void sil24_port_stop(struct ata_port *ap) { struct device *dev = ap->host_set->dev; struct sil24_port_priv *pp = ap->private_data; - size_t cb_size = sizeof(*pp->cmd_block); - dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); + sil24_cblk_free(pp, dev); kfree(pp); } diff --git a/include/linux/libata.h b/include/linux/libata.h index 6225b78fa65b..dcd17e7458ab 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -777,4 +777,17 @@ static inline unsigned int __ac_err_mask(u8 status) return mask; } +static inline int ata_pad_alloc(struct ata_port *ap, struct device *dev) +{ + ap->pad_dma = 0; + ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, + &ap->pad_dma, GFP_KERNEL); + return (ap->pad == NULL) ? -ENOMEM : 0; +} + +static inline void ata_pad_free(struct ata_port *ap, struct device *dev) +{ + dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); +} + #endif /* __LINUX_LIBATA_H__ */ -- cgit v1.2.3 From f896424cbc61225e8f029fe23e5aae3e32103229 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 2 Nov 2005 16:13:06 -0700 Subject: [PATCH] phy address mask support for generic phy layer Adds a phy_mask field to struct mii_bus and uses it. This field indicates each phy address to be ignored when probing the mdio bus. This support is needed for the fs_enet and ibm_emac drivers to be converted to the generic phy layer among other drivers. Many systems lock up on probing certain phy addresses or probing doesn't return 0xffff when nothing is found at the address. A new driver I'm working on also makes use of this mask. Signed-off-by: Matt Porter Signed-off-by: Jeff Garzik --- drivers/net/phy/mdio_bus.c | 3 +++ include/linux/phy.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'include') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index ad93b0da87f0..5eab9c42a111 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -61,6 +61,9 @@ int mdiobus_register(struct mii_bus *bus) for (i = 0; i < PHY_MAX_ADDR; i++) { struct phy_device *phydev; + if (bus->phy_mask & (1 << i)) + continue; + phydev = get_phy_device(bus, i); if (IS_ERR(phydev)) diff --git a/include/linux/phy.h b/include/linux/phy.h index 72cb67b66e0c..92a9696fdebe 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -72,6 +72,9 @@ struct mii_bus { /* list of all PHYs on bus */ struct phy_device *phy_map[PHY_MAX_ADDR]; + /* Phy addresses to be ignored when probing */ + u32 phy_mask; + /* Pointer to an array of interrupts, each PHY's * interrupt at the index matching its address */ int *irq; -- cgit v1.2.3 From a783474591f2eed0348e08b15934fa9a25e23b3e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:03 +0100 Subject: [PKT_SCHED]: Generic RED layer Extracts the RED algorithm from sch_red.c and puts it into include/net/red.h for use by other RED based modules. The statistics are extended to be more fine grained in order to differ between probability/forced marks/drops. We now reset the average queue length when setting new parameters, leaving it might result in an unreasonable qavg for a while depending on the value of W. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/net/red.h | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 include/net/red.h (limited to 'include') diff --git a/include/net/red.h b/include/net/red.h new file mode 100644 index 000000000000..2ed4358e3295 --- /dev/null +++ b/include/net/red.h @@ -0,0 +1,325 @@ +#ifndef __NET_SCHED_RED_H +#define __NET_SCHED_RED_H + +#include +#include +#include +#include +#include + +/* Random Early Detection (RED) algorithm. + ======================================= + + Source: Sally Floyd and Van Jacobson, "Random Early Detection Gateways + for Congestion Avoidance", 1993, IEEE/ACM Transactions on Networking. + + This file codes a "divisionless" version of RED algorithm + as written down in Fig.17 of the paper. + + Short description. + ------------------ + + When a new packet arrives we calculate the average queue length: + + avg = (1-W)*avg + W*current_queue_len, + + W is the filter time constant (chosen as 2^(-Wlog)), it controls + the inertia of the algorithm. To allow larger bursts, W should be + decreased. + + if (avg > th_max) -> packet marked (dropped). + if (avg < th_min) -> packet passes. + if (th_min < avg < th_max) we calculate probability: + + Pb = max_P * (avg - th_min)/(th_max-th_min) + + and mark (drop) packet with this probability. + Pb changes from 0 (at avg==th_min) to max_P (avg==th_max). + max_P should be small (not 1), usually 0.01..0.02 is good value. + + max_P is chosen as a number, so that max_P/(th_max-th_min) + is a negative power of two in order arithmetics to contain + only shifts. + + + Parameters, settable by user: + ----------------------------- + + qth_min - bytes (should be < qth_max/2) + qth_max - bytes (should be at least 2*qth_min and less limit) + Wlog - bits (<32) log(1/W). + Plog - bits (<32) + + Plog is related to max_P by formula: + + max_P = (qth_max-qth_min)/2^Plog; + + F.e. if qth_max=128K and qth_min=32K, then Plog=22 + corresponds to max_P=0.02 + + Scell_log + Stab + + Lookup table for log((1-W)^(t/t_ave). + + + NOTES: + + Upper bound on W. + ----------------- + + If you want to allow bursts of L packets of size S, + you should choose W: + + L + 1 - th_min/S < (1-(1-W)^L)/W + + th_min/S = 32 th_min/S = 4 + + log(W) L + -1 33 + -2 35 + -3 39 + -4 46 + -5 57 + -6 75 + -7 101 + -8 135 + -9 190 + etc. + */ + +#define RED_STAB_SIZE 256 +#define RED_STAB_MASK (RED_STAB_SIZE - 1) + +struct red_stats +{ + u32 prob_drop; /* Early probability drops */ + u32 prob_mark; /* Early probability marks */ + u32 forced_drop; /* Forced drops, qavg > max_thresh */ + u32 forced_mark; /* Forced marks, qavg > max_thresh */ + u32 pdrop; /* Drops due to queue limits */ + u32 other; /* Drops due to drop() calls */ + u32 backlog; +}; + +struct red_parms +{ + /* Parameters */ + u32 qth_min; /* Min avg length threshold: A scaled */ + u32 qth_max; /* Max avg length threshold: A scaled */ + u32 Scell_max; + u32 Rmask; /* Cached random mask, see red_rmask */ + u8 Scell_log; + u8 Wlog; /* log(W) */ + u8 Plog; /* random number bits */ + u8 Stab[RED_STAB_SIZE]; + + /* Variables */ + int qcount; /* Number of packets since last random + number generation */ + u32 qR; /* Cached random number */ + + unsigned long qavg; /* Average queue length: A scaled */ + psched_time_t qidlestart; /* Start of current idle period */ +}; + +static inline u32 red_rmask(u8 Plog) +{ + return Plog < 32 ? ((1 << Plog) - 1) : ~0UL; +} + +static inline void red_set_parms(struct red_parms *p, + u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, + u8 Scell_log, u8 *stab) +{ + /* Reset average queue length, the value is strictly bound + * to the parameters below, reseting hurts a bit but leaving + * it might result in an unreasonable qavg for a while. --TGR + */ + p->qavg = 0; + + p->qcount = -1; + p->qth_min = qth_min << Wlog; + p->qth_max = qth_max << Wlog; + p->Wlog = Wlog; + p->Plog = Plog; + p->Rmask = red_rmask(Plog); + p->Scell_log = Scell_log; + p->Scell_max = (255 << Scell_log); + + memcpy(p->Stab, stab, sizeof(p->Stab)); +} + +static inline int red_is_idling(struct red_parms *p) +{ + return !PSCHED_IS_PASTPERFECT(p->qidlestart); +} + +static inline void red_start_of_idle_period(struct red_parms *p) +{ + PSCHED_GET_TIME(p->qidlestart); +} + +static inline void red_end_of_idle_period(struct red_parms *p) +{ + PSCHED_SET_PASTPERFECT(p->qidlestart); +} + +static inline void red_restart(struct red_parms *p) +{ + red_end_of_idle_period(p); + p->qavg = 0; + p->qcount = -1; +} + +static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) +{ + psched_time_t now; + long us_idle; + int shift; + + PSCHED_GET_TIME(now); + us_idle = PSCHED_TDIFF_SAFE(now, p->qidlestart, p->Scell_max); + + /* + * The problem: ideally, average length queue recalcultion should + * be done over constant clock intervals. This is too expensive, so + * that the calculation is driven by outgoing packets. + * When the queue is idle we have to model this clock by hand. + * + * SF+VJ proposed to "generate": + * + * m = idletime / (average_pkt_size / bandwidth) + * + * dummy packets as a burst after idle time, i.e. + * + * p->qavg *= (1-W)^m + * + * This is an apparently overcomplicated solution (f.e. we have to + * precompute a table to make this calculation in reasonable time) + * I believe that a simpler model may be used here, + * but it is field for experiments. + */ + + shift = p->Stab[(us_idle >> p->Scell_log) & RED_STAB_MASK]; + + if (shift) + return p->qavg >> shift; + else { + /* Approximate initial part of exponent with linear function: + * + * (1-W)^m ~= 1-mW + ... + * + * Seems, it is the best solution to + * problem of too coarse exponent tabulation. + */ + us_idle = (p->qavg * us_idle) >> p->Scell_log; + + if (us_idle < (p->qavg >> 1)) + return p->qavg - us_idle; + else + return p->qavg >> 1; + } +} + +static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p, + unsigned int backlog) +{ + /* + * NOTE: p->qavg is fixed point number with point at Wlog. + * The formula below is equvalent to floating point + * version: + * + * qavg = qavg*(1-W) + backlog*W; + * + * --ANK (980924) + */ + return p->qavg + (backlog - (p->qavg >> p->Wlog)); +} + +static inline unsigned long red_calc_qavg(struct red_parms *p, + unsigned int backlog) +{ + if (!red_is_idling(p)) + return red_calc_qavg_no_idle_time(p, backlog); + else + return red_calc_qavg_from_idle_time(p); +} + +static inline u32 red_random(struct red_parms *p) +{ + return net_random() & p->Rmask; +} + +static inline int red_mark_probability(struct red_parms *p, unsigned long qavg) +{ + /* The formula used below causes questions. + + OK. qR is random number in the interval 0..Rmask + i.e. 0..(2^Plog). If we used floating point + arithmetics, it would be: (2^Plog)*rnd_num, + where rnd_num is less 1. + + Taking into account, that qavg have fixed + point at Wlog, and Plog is related to max_P by + max_P = (qth_max-qth_min)/2^Plog; two lines + below have the following floating point equivalent: + + max_P*(qavg - qth_min)/(qth_max-qth_min) < rnd/qcount + + Any questions? --ANK (980924) + */ + return !(((qavg - p->qth_min) >> p->Wlog) * p->qcount < p->qR); +} + +enum { + RED_BELOW_MIN_THRESH, + RED_BETWEEN_TRESH, + RED_ABOVE_MAX_TRESH, +}; + +static inline int red_cmp_thresh(struct red_parms *p, unsigned long qavg) +{ + if (qavg < p->qth_min) + return RED_BELOW_MIN_THRESH; + else if (qavg >= p->qth_max) + return RED_ABOVE_MAX_TRESH; + else + return RED_BETWEEN_TRESH; +} + +enum { + RED_DONT_MARK, + RED_PROB_MARK, + RED_HARD_MARK, +}; + +static inline int red_action(struct red_parms *p, unsigned long qavg) +{ + switch (red_cmp_thresh(p, qavg)) { + case RED_BELOW_MIN_THRESH: + p->qcount = -1; + return RED_DONT_MARK; + + case RED_BETWEEN_TRESH: + if (++p->qcount) { + if (red_mark_probability(p, qavg)) { + p->qcount = 0; + p->qR = red_random(p); + return RED_PROB_MARK; + } + } else + p->qR = red_random(p); + + return RED_DONT_MARK; + + case RED_ABOVE_MAX_TRESH: + p->qcount = -1; + return RED_HARD_MARK; + } + + BUG(); + return RED_DONT_MARK; +} + +#endif -- cgit v1.2.3 From 2566a509cacc8b8eaea2e5b54068816c9cfb41c2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:04 +0100 Subject: [NET]: Introduce INET_ECN_set_ce() function Changes IP_ECN_set_ce() and IP6_ECN_set_ce() to return 0 if the CE bits could not bet set because none of the ECT bits are set or 1 if the CE bits are already set or have been successfully set. Introduces INET_ECN_set_ce(skb) to enable CE bits for all supported protocols. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/net/inet_ecn.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index f87845e2e965..b0c47e2eccf1 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -2,6 +2,7 @@ #define _INET_ECN_H_ #include +#include #include enum { @@ -48,7 +49,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) (label) |= __constant_htons(INET_ECN_ECT_0 << 4); \ } while (0) -static inline void IP_ECN_set_ce(struct iphdr *iph) +static inline int IP_ECN_set_ce(struct iphdr *iph) { u32 check = iph->check; u32 ecn = (iph->tos + 1) & INET_ECN_MASK; @@ -61,7 +62,7 @@ static inline void IP_ECN_set_ce(struct iphdr *iph) * INET_ECN_CE => 00 */ if (!(ecn & 2)) - return; + return !ecn; /* * The following gives us: @@ -72,6 +73,7 @@ static inline void IP_ECN_set_ce(struct iphdr *iph) iph->check = check + (check>=0xFFFF); iph->tos |= INET_ECN_CE; + return 1; } static inline void IP_ECN_clear(struct iphdr *iph) @@ -87,11 +89,12 @@ static inline void ipv4_copy_dscp(struct iphdr *outer, struct iphdr *inner) struct ipv6hdr; -static inline void IP6_ECN_set_ce(struct ipv6hdr *iph) +static inline int IP6_ECN_set_ce(struct ipv6hdr *iph) { if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) - return; + return 0; *(u32*)iph |= htonl(INET_ECN_CE << 20); + return 1; } static inline void IP6_ECN_clear(struct ipv6hdr *iph) @@ -105,4 +108,21 @@ static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner) ipv6_change_dsfield(inner, INET_ECN_MASK, dscp); } +static inline int INET_ECN_set_ce(struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + if (skb->nh.raw + sizeof(struct iphdr) <= skb->tail) + return IP_ECN_set_ce(skb->nh.iph); + break; + + case __constant_htons(ETH_P_IPV6): + if (skb->nh.raw + sizeof(struct ipv6hdr) <= skb->tail) + return IP6_ECN_set_ce(skb->nh.ipv6h); + break; + } + + return 0; +} + #endif -- cgit v1.2.3 From 1e4dfaf9b99a8b652e8421936fd5fe2459da8265 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:25 +0100 Subject: [PKT_SCHED]: GRED: Cleanup and remove unnecessary code Removes unnecessary includes, initializers, and simplifies the code a bit. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 48 ++++++++++------------ net/sched/sch_gred.c | 100 ++++++++++++++-------------------------------- 2 files changed, 53 insertions(+), 95 deletions(-) (limited to 'include') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 60ffcb9c5791..d053add3dca7 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -194,38 +194,34 @@ enum #define TCA_GRED_MAX (__TCA_GRED_MAX - 1) -#define TCA_SET_OFF TCA_GRED_PARMS struct tc_gred_qopt { - __u32 limit; /* HARD maximal queue length (bytes) -*/ - __u32 qth_min; /* Min average length threshold (bytes) -*/ - __u32 qth_max; /* Max average length threshold (bytes) -*/ - __u32 DP; /* upto 2^32 DPs */ - __u32 backlog; - __u32 qave; - __u32 forced; - __u32 early; - __u32 other; - __u32 pdrop; - - unsigned char Wlog; /* log(W) */ - unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ - unsigned char Scell_log; /* cell size for idle damping */ - __u8 prio; /* prio of this VQ */ - __u32 packets; - __u32 bytesin; + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + __u32 DP; /* upto 2^32 DPs */ + __u32 backlog; + __u32 qave; + __u32 forced; + __u32 early; + __u32 other; + __u32 pdrop; + __u8 Wlog; /* log(W) */ + __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ + __u8 Scell_log; /* cell size for idle damping */ + __u8 prio; /* prio of this VQ */ + __u32 packets; + __u32 bytesin; }; + /* gred setup */ struct tc_gred_sopt { - __u32 DPs; - __u32 def_DP; - __u8 grio; - __u8 pad1; - __u16 pad2; + __u32 DPs; + __u32 def_DP; + __u8 grio; + __u8 pad1; + __u16 pad2; }; /* HTB section */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 897e6df81b1f..1fb34be32f7c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -15,50 +15,18 @@ * from Ren Liu * - More error checks * - * - * - * For all the glorious comments look at Alexey's sch_red.c + * For all the glorious comments look at include/net/red.h */ #include #include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include #include -#if 1 /* control */ -#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define DPRINTK(format,args...) -#endif - -#if 0 /* data */ -#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define D2PRINTK(format,args...) -#endif - #define GRED_DEF_PRIO (MAX_DPs / 2) #define GRED_VQ_MASK (MAX_DPs - 1) @@ -72,7 +40,7 @@ struct gred_sched_data u32 bytesin; /* bytes seen on virtualQ so far*/ u32 packetsin; /* packets seen on virtualQ so far*/ u32 backlog; /* bytes on the virtualQ */ - u8 prio; /* the prio of this vq */ + u8 prio; /* the prio of this vq */ struct red_parms parms; struct red_stats stats; @@ -87,8 +55,8 @@ struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; unsigned long flags; - u32 DPs; - u32 def; + u32 DPs; + u32 def; struct red_parms wred_set; }; @@ -172,13 +140,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, table->wred_set.qavg = q->parms.qavg; } -static int -gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) +static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; struct gred_sched *t= qdisc_priv(sch); unsigned long qavg = 0; - int i=0; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -200,26 +166,23 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp; } - /* sum up all the qaves of prios <= to ours to get the new qave*/ + /* sum up all the qaves of prios <= to ours to get the new qave */ if (!gred_wred_mode(t) && gred_rio_mode(t)) { - for (i=0;iDPs;i++) { - if ((!t->tab[i]) || (i==q->DP)) - continue; - - if (t->tab[i]->prio < q->prio && + int i; + + for (i = 0; i < t->DPs; i++) { + if (t->tab[i] && t->tab[i]->prio < q->prio && !red_is_idling(&t->tab[i]->parms)) qavg +=t->tab[i]->parms.qavg; } - + } q->packetsin++; - q->bytesin+=skb->len; + q->bytesin += skb->len; - if (gred_wred_mode(t)) { - qavg = 0; + if (gred_wred_mode(t)) gred_load_wred_set(t, q); - } q->parms.qavg = red_calc_qavg(&q->parms, gred_backlog(t, q, sch)); @@ -258,8 +221,7 @@ congestion_drop: return NET_XMIT_CN; } -static int -gred_requeue(struct sk_buff *skb, struct Qdisc* sch) +static int gred_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched *t = qdisc_priv(sch); struct gred_sched_data *q; @@ -279,16 +241,15 @@ gred_requeue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_requeue(skb, sch); } -static struct sk_buff * -gred_dequeue(struct Qdisc* sch) +static struct sk_buff *gred_dequeue(struct Qdisc* sch) { struct sk_buff *skb; - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); skb = qdisc_dequeue_head(sch); if (skb) { + struct gred_sched_data *q; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -315,13 +276,12 @@ gred_dequeue(struct Qdisc* sch) static unsigned int gred_drop(struct Qdisc* sch) { struct sk_buff *skb; - - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; + struct gred_sched_data *q; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -351,15 +311,16 @@ static unsigned int gred_drop(struct Qdisc* sch) static void gred_reset(struct Qdisc* sch) { int i; - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); qdisc_reset_queue(sch); - for (i=0;iDPs;i++) { - q= t->tab[i]; - if (!q) - continue; + for (i = 0; i < t->DPs; i++) { + struct gred_sched_data *q = t->tab[i]; + + if (!q) + continue; + red_restart(&q->parms); q->backlog = 0; } @@ -590,15 +551,13 @@ static void gred_destroy(struct Qdisc *sch) struct gred_sched *table = qdisc_priv(sch); int i; - for (i = 0;i < table->DPs; i++) { + for (i = 0; i < table->DPs; i++) { if (table->tab[i]) gred_destroy_vq(table->tab[i]); } } static struct Qdisc_ops gred_qdisc_ops = { - .next = NULL, - .cl_ops = NULL, .id = "gred", .priv_size = sizeof(struct gred_sched), .enqueue = gred_enqueue, @@ -617,10 +576,13 @@ static int __init gred_module_init(void) { return register_qdisc(&gred_qdisc_ops); } -static void __exit gred_module_exit(void) + +static void __exit gred_module_exit(void) { unregister_qdisc(&gred_qdisc_ops); } + module_init(gred_module_init) module_exit(gred_module_exit) + MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b38c7eef7e536d12051cc3d5864032f2f907cdfe Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:27 +0100 Subject: [PKT_SCHED]: GRED: Support ECN marking Adds a new u8 flags in a unused padding area of the netlink message. Adds ECN marking support to be used instead of dropping packets immediately. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 4 ++-- net/sched/sch_gred.c | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index d053add3dca7..0ebe320223e2 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -220,8 +220,8 @@ struct tc_gred_sopt __u32 DPs; __u32 def_DP; __u8 grio; - __u8 pad1; - __u16 pad2; + __u8 flags; + __u16 pad1; }; /* HTB section */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 69f0fd45d4c3..079b0a4ea1c2 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -55,6 +55,7 @@ struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; unsigned long flags; + u32 red_flags; u32 DPs; u32 def; struct red_parms wred_set; @@ -140,6 +141,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, table->wred_set.qavg = q->parms.qavg; } +static inline int gred_use_ecn(struct gred_sched *t) +{ + return t->red_flags & TC_RED_ECN; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; @@ -198,13 +204,22 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_PROB_MARK: sch->qstats.overlimits++; - q->stats.prob_drop++; - goto congestion_drop; + if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + q->stats.prob_drop++; + goto congestion_drop; + } + + q->stats.prob_mark++; + break; case RED_HARD_MARK: sch->qstats.overlimits++; - q->stats.forced_drop++; - goto congestion_drop; + if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + q->stats.forced_drop++; + goto congestion_drop; + } + q->stats.forced_mark++; + break; } if (q->backlog + skb->len <= q->limit) { @@ -348,6 +363,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) sch_tree_lock(sch); table->DPs = sopt->DPs; table->def = sopt->def_DP; + table->red_flags = sopt->flags; /* * Every entry point to GRED is synchronized with the above code @@ -489,6 +505,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) .DPs = table->DPs, .def_DP = table->def, .grio = gred_rio_mode(table), + .flags = table->red_flags, }; opts = RTA_NEST(skb, TCA_OPTIONS); -- cgit v1.2.3 From bdc450a0bb1d48144ced1f899cc8366ec8e85024 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:28 +0100 Subject: [PKT_SCHED]: (G)RED: Introduce hard dropping Introduces a new flag TC_RED_HARDDROP which specifies that if ECN marking is enabled packets should still be dropped once the average queue length exceeds the maximum threshold. This _may_ help to avoid global synchronisation during small bursts of peers advertising but not caring about ECN. Use this option very carefully, it does more harm than good if (qth_max - qth_min) does not cover at least two average burst cycles. The difference to the current behaviour, in which we'd run into the hard queue limit, is that due to the low pass filter of RED short bursts are less likely to cause a global synchronisation. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 2 ++ net/sched/sch_gred.c | 8 +++++++- net/sched/sch_red.c | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 0ebe320223e2..e87b233615b3 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -93,6 +93,7 @@ struct tc_fifo_qopt /* PRIO section */ #define TCQ_PRIO_BANDS 16 +#define TCQ_MIN_PRIO_BANDS 2 struct tc_prio_qopt { @@ -169,6 +170,7 @@ struct tc_red_qopt unsigned char Scell_log; /* cell size for idle damping */ unsigned char flags; #define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 }; struct tc_red_xstats diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 079b0a4ea1c2..29a2dd9f3029 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -146,6 +146,11 @@ static inline int gred_use_ecn(struct gred_sched *t) return t->red_flags & TC_RED_ECN; } +static inline int gred_use_harddrop(struct gred_sched *t) +{ + return t->red_flags & TC_RED_HARDDROP; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; @@ -214,7 +219,8 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_HARD_MARK: sch->qstats.overlimits++; - if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + if (gred_use_harddrop(t) || !gred_use_ecn(t) || + !INET_ECN_set_ce(skb)) { q->stats.forced_drop++; goto congestion_drop; } diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 0d89dee751a9..dccfa44c2d71 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -51,6 +51,11 @@ static inline int red_use_ecn(struct red_sched_data *q) return q->flags & TC_RED_ECN; } +static inline int red_use_harddrop(struct red_sched_data *q) +{ + return q->flags & TC_RED_HARDDROP; +} + static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); @@ -76,7 +81,8 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_HARD_MARK: sch->qstats.overlimits++; - if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { + if (red_use_harddrop(q) || !red_use_ecn(q) || + !INET_ECN_set_ce(skb)) { q->stats.forced_drop++; goto congestion_drop; } -- cgit v1.2.3 From 37c12e7497b6fe2b6a890814f0ff4edce696d862 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:19:33 +0000 Subject: [DRIVER MODEL] Improved dynamically allocated platform_device interface Re-jig the simple platform device support to allow private data to be attached to a platform device, as well as allowing the parent device to be set. Example usage: pdev = platform_device_alloc("mydev", id); if (pdev) { err = platform_device_add_resources(pdev, &resources, ARRAY_SIZE(resources)); if (err == 0) err = platform_device_add_data(pdev, &platform_data, sizeof(platform_data)); if (err == 0) err = platform_device_add(pdev); } else { err = -ENOMEM; } if (err) platform_device_put(pdev); Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/base/platform.c | 153 +++++++++++++++++++++++++++++++++------- include/linux/platform_device.h | 6 ++ 2 files changed, 132 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d597c922af11..6d4736e89f1a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -116,12 +116,115 @@ int platform_add_devices(struct platform_device **devs, int num) return ret; } +struct platform_object { + struct platform_device pdev; + char name[1]; +}; + /** - * platform_device_register - add a platform-level device + * platform_device_put + * @pdev: platform device to free + * + * Free all memory associated with a platform device. This function + * must _only_ be externally called in error cases. All other usage + * is a bug. + */ +void platform_device_put(struct platform_device *pdev) +{ + if (pdev) + put_device(&pdev->dev); +} +EXPORT_SYMBOL_GPL(platform_device_put); + +static void platform_device_release(struct device *dev) +{ + struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev); + + kfree(pa->pdev.dev.platform_data); + kfree(pa->pdev.resource); + kfree(pa); +} + +/** + * platform_device_alloc + * @name: base name of the device we're adding + * @id: instance id + * + * Create a platform device object which can have other objects attached + * to it, and which will have attached objects freed when it is released. + */ +struct platform_device *platform_device_alloc(const char *name, unsigned int id) +{ + struct platform_object *pa; + + pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); + if (pa) { + strcpy(pa->name, name); + pa->pdev.name = pa->name; + pa->pdev.id = id; + device_initialize(&pa->pdev.dev); + pa->pdev.dev.release = platform_device_release; + } + + return pa ? &pa->pdev : NULL; +} +EXPORT_SYMBOL_GPL(platform_device_alloc); + +/** + * platform_device_add_resources + * @pdev: platform device allocated by platform_device_alloc to add resources to + * @res: set of resources that needs to be allocated for the device + * @num: number of resources + * + * Add a copy of the resources to the platform device. The memory + * associated with the resources will be freed when the platform + * device is released. + */ +int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num) +{ + struct resource *r; + + r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); + if (r) { + memcpy(r, res, sizeof(struct resource) * num); + pdev->resource = r; + pdev->num_resources = num; + } + return r ? 0 : -ENOMEM; +} +EXPORT_SYMBOL_GPL(platform_device_add_resources); + +/** + * platform_device_add_data + * @pdev: platform device allocated by platform_device_alloc to add resources to + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Add a copy of platform specific data to the platform device's platform_data + * pointer. The memory associated with the platform data will be freed + * when the platform device is released. + */ +int platform_device_add_data(struct platform_device *pdev, void *data, size_t size) +{ + void *d; + + d = kmalloc(size, GFP_KERNEL); + if (d) { + memcpy(d, data, size); + pdev->dev.platform_data = d; + } + return d ? 0 : -ENOMEM; +} +EXPORT_SYMBOL_GPL(platform_device_add_data); + +/** + * platform_device_add - add a platform device to device hierarchy * @pdev: platform device we're adding * + * This is part 2 of platform_device_register(), though may be called + * separately _iff_ pdev was allocated by platform_device_alloc(). */ -int platform_device_register(struct platform_device * pdev) +int platform_device_add(struct platform_device *pdev) { int i, ret = 0; @@ -174,6 +277,18 @@ int platform_device_register(struct platform_device * pdev) release_resource(&pdev->resource[i]); return ret; } +EXPORT_SYMBOL_GPL(platform_device_add); + +/** + * platform_device_register - add a platform-level device + * @pdev: platform device we're adding + * + */ +int platform_device_register(struct platform_device * pdev) +{ + device_initialize(&pdev->dev); + return platform_device_add(pdev); +} /** * platform_device_unregister - remove a platform-level device @@ -197,18 +312,6 @@ void platform_device_unregister(struct platform_device * pdev) } } -struct platform_object { - struct platform_device pdev; - struct resource resources[0]; -}; - -static void platform_device_release_simple(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - - kfree(container_of(pdev, struct platform_object, pdev)); -} - /** * platform_device_register_simple * @name: base name of the device we're adding @@ -225,33 +328,29 @@ static void platform_device_release_simple(struct device *dev) struct platform_device *platform_device_register_simple(char *name, unsigned int id, struct resource *res, unsigned int num) { - struct platform_object *pobj; + struct platform_device *pdev; int retval; - pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL); - if (!pobj) { + pdev = platform_device_alloc(name, id); + if (!pdev) { retval = -ENOMEM; goto error; } - pobj->pdev.name = name; - pobj->pdev.id = id; - pobj->pdev.dev.release = platform_device_release_simple; - if (num) { - memcpy(pobj->resources, res, sizeof(struct resource) * num); - pobj->pdev.resource = pobj->resources; - pobj->pdev.num_resources = num; + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto error; } - retval = platform_device_register(&pobj->pdev); + retval = platform_device_add(pdev); if (retval) goto error; - return &pobj->pdev; + return pdev; error: - kfree(pobj); + platform_device_put(pdev); return ERR_PTR(retval); } diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index a726225e0afe..1a165b7ae01b 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -37,4 +37,10 @@ extern int platform_add_devices(struct platform_device **, int); extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int); +extern struct platform_device *platform_device_alloc(const char *name, unsigned int id); +extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); +extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size); +extern int platform_device_add(struct platform_device *pdev); +extern void platform_device_put(struct platform_device *pdev); + #endif /* _PLATFORM_DEVICE_H_ */ -- cgit v1.2.3 From 300ce174ebc2fcf2b5111a50fa42f79d891927dd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 30 Oct 2005 13:47:34 -0800 Subject: [NETEM]: Support time based reordering Change netem to support packets getting reordered because of variations in delay. Introduce a special case version of FIFO that queues packets in order based on the netem delay. Since netem is classful, those users that don't want jitter based reordering can just insert a pfifo instead of the default. This required changes to generic skbuff code to allow finer grain manipulation of sk_buff_head. Insertion into the middle and reverse walk. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/skbuff.h | 38 +++++++++++++++++----- net/sched/sch_netem.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4286d832166f..fdfb8fe8c38c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -603,29 +603,46 @@ static inline void skb_queue_head_init(struct sk_buff_head *list) */ /** - * __skb_queue_head - queue a buffer at the list head + * __skb_queue_after - queue a buffer at the list head * @list: list to use + * @prev: place after this buffer * @newsk: buffer to queue * - * Queue a buffer at the start of a list. This function takes no locks + * Queue a buffer int the middle of a list. This function takes no locks * and you must therefore hold required locks before calling it. * * A buffer cannot be placed on two lists at the same time. */ -extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); -static inline void __skb_queue_head(struct sk_buff_head *list, - struct sk_buff *newsk) +static inline void __skb_queue_after(struct sk_buff_head *list, + struct sk_buff *prev, + struct sk_buff *newsk) { - struct sk_buff *prev, *next; - + struct sk_buff *next; list->qlen++; - prev = (struct sk_buff *)list; + next = prev->next; newsk->next = next; newsk->prev = prev; next->prev = prev->next = newsk; } +/** + * __skb_queue_head - queue a buffer at the list head + * @list: list to use + * @newsk: buffer to queue + * + * Queue a buffer at the start of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + * + * A buffer cannot be placed on two lists at the same time. + */ +extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); +static inline void __skb_queue_head(struct sk_buff_head *list, + struct sk_buff *newsk) +{ + __skb_queue_after(list, (struct sk_buff *)list, newsk); +} + /** * __skb_queue_tail - queue a buffer at the list tail * @list: list to use @@ -1203,6 +1220,11 @@ static inline void kunmap_skb_frag(void *vaddr) prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ skb = skb->next) +#define skb_queue_reverse_walk(queue, skb) \ + for (skb = (queue)->prev; \ + prefetch(skb->prev), (skb != (struct sk_buff *)(queue)); \ + skb = skb->prev) + extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index d871fe7f81a9..7c10ef3457d7 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -300,11 +300,16 @@ static void netem_reset(struct Qdisc *sch) del_timer_sync(&q->timer); } +/* Pass size change message down to embedded FIFO */ static int set_fifo_limit(struct Qdisc *q, int limit) { struct rtattr *rta; int ret = -ENOMEM; + /* Hack to avoid sending change message to non-FIFO */ + if (strncmp(q->ops->id + 1, "fifo", 4) != 0) + return 0; + rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { rta->rta_type = RTM_NEWQDISC; @@ -436,6 +441,84 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) return 0; } +/* + * Special case version of FIFO queue for use by netem. + * It queues in order based on timestamps in skb's + */ +struct fifo_sched_data { + u32 limit; +}; + +static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + struct sk_buff_head *list = &sch->q; + const struct netem_skb_cb *ncb + = (const struct netem_skb_cb *)nskb->cb; + struct sk_buff *skb; + + if (likely(skb_queue_len(list) < q->limit)) { + skb_queue_reverse_walk(list, skb) { + const struct netem_skb_cb *cb + = (const struct netem_skb_cb *)skb->cb; + + if (PSCHED_TLESS(cb->time_to_send, ncb->time_to_send)) + break; + } + + __skb_queue_after(list, skb, nskb); + + sch->qstats.backlog += nskb->len; + sch->bstats.bytes += nskb->len; + sch->bstats.packets++; + + return NET_XMIT_SUCCESS; + } + + return qdisc_drop(nskb, sch); +} + +static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + + if (opt) { + struct tc_fifo_qopt *ctl = RTA_DATA(opt); + if (RTA_PAYLOAD(opt) < sizeof(*ctl)) + return -EINVAL; + + q->limit = ctl->limit; + } else + q->limit = max_t(u32, sch->dev->tx_queue_len, 1); + + return 0; +} + +static int tfifo_dump(struct Qdisc *sch, struct sk_buff *skb) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + struct tc_fifo_qopt opt = { .limit = q->limit }; + + RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + return skb->len; + +rtattr_failure: + return -1; +} + +static struct Qdisc_ops tfifo_qdisc_ops = { + .id = "tfifo", + .priv_size = sizeof(struct fifo_sched_data), + .enqueue = tfifo_enqueue, + .dequeue = qdisc_dequeue_head, + .requeue = qdisc_requeue, + .drop = qdisc_queue_drop, + .init = tfifo_init, + .reset = qdisc_reset_queue, + .change = tfifo_init, + .dump = tfifo_dump, +}; + static int netem_init(struct Qdisc *sch, struct rtattr *opt) { struct netem_sched_data *q = qdisc_priv(sch); @@ -448,7 +531,7 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; - q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops); if (!q->qdisc) { pr_debug("netem: qdisc create failed\n"); return -ENOMEM; -- cgit v1.2.3 From 6df716340da3a6fdd33d73d7ed4c6f7590ca1c42 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 3 Nov 2005 16:33:23 -0800 Subject: [TCP/DCCP]: Randomize port selection This patch randomizes the port selected on bind() for connections to help with possible security attacks. It should also be faster in most cases because there is no need for a global lock. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/net/inet_hashtables.h | 2 -- net/dccp/ipv4.c | 32 +++----------------------------- net/ipv4/inet_connection_sock.c | 14 +++----------- net/ipv4/tcp.c | 1 - net/ipv4/tcp_ipv4.c | 2 -- net/ipv6/tcp_ipv6.c | 15 ++++----------- 6 files changed, 10 insertions(+), 56 deletions(-) (limited to 'include') diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index f50f95968340..07840baa9341 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -125,9 +125,7 @@ struct inet_hashinfo { rwlock_t lhash_lock ____cacheline_aligned; atomic_t lhash_users; wait_queue_head_t lhash_wait; - spinlock_t portalloc_lock; kmem_cache_t *bind_bucket_cachep; - int port_rover; }; static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 6298cf58ff9e..4b9bc81ae1a3 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -31,8 +31,6 @@ struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { .lhash_lock = RW_LOCK_UNLOCKED, .lhash_users = ATOMIC_INIT(0), .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait), - .portalloc_lock = SPIN_LOCK_UNLOCKED, - .port_rover = 1024 - 1, }; EXPORT_SYMBOL_GPL(dccp_hashinfo); @@ -125,36 +123,15 @@ static int dccp_v4_hash_connect(struct sock *sk) int ret; if (snum == 0) { - int rover; int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; int remaining = (high - low) + 1; + int rover = net_random() % (high - low) + low; struct hlist_node *node; struct inet_timewait_sock *tw = NULL; local_bh_disable(); - - /* TODO. Actually it is not so bad idea to remove - * dccp_hashinfo.portalloc_lock before next submission to - * Linus. - * As soon as we touch this place at all it is time to think. - * - * Now it protects single _advisory_ variable - * dccp_hashinfo.port_rover, hence it is mostly useless. - * Code will work nicely if we just delete it, but - * I am afraid in contented case it will work not better or - * even worse: another cpu just will hit the same bucket - * and spin there. - * So some cpu salt could remove both contention and - * memory pingpong. Any ideas how to do this in a nice way? - */ - spin_lock(&dccp_hashinfo.portalloc_lock); - rover = dccp_hashinfo.port_rover; - do { - rover++; - if ((rover < low) || (rover > high)) - rover = low; head = &dccp_hashinfo.bhash[inet_bhashfn(rover, dccp_hashinfo.bhash_size)]; spin_lock(&head->lock); @@ -187,9 +164,9 @@ static int dccp_v4_hash_connect(struct sock *sk) next_port: spin_unlock(&head->lock); + if (++rover > high) + rover = low; } while (--remaining > 0); - dccp_hashinfo.port_rover = rover; - spin_unlock(&dccp_hashinfo.portalloc_lock); local_bh_enable(); @@ -197,9 +174,6 @@ static int dccp_v4_hash_connect(struct sock *sk) ok: /* All locks still held and bhs disabled */ - dccp_hashinfo.port_rover = rover; - spin_unlock(&dccp_hashinfo.portalloc_lock); - inet_bind_hash(sk, tb, rover); if (sk_unhashed(sk)) { inet_sk(sk)->sport = htons(rover); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 94468a76c5b4..3fe021f1a566 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -78,17 +78,9 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; int remaining = (high - low) + 1; - int rover; + int rover = net_random() % (high - low) + low; - spin_lock(&hashinfo->portalloc_lock); - if (hashinfo->port_rover < low) - rover = low; - else - rover = hashinfo->port_rover; do { - rover++; - if (rover > high) - rover = low; head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) @@ -97,9 +89,9 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, break; next: spin_unlock(&head->lock); + if (++rover > high) + rover = low; } while (--remaining > 0); - hashinfo->port_rover = rover; - spin_unlock(&hashinfo->portalloc_lock); /* Exhausted local port range during search? It is not * possible for us to be holding one of the bind hash diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f3f0013a9580..72b7c22e1ea5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2112,7 +2112,6 @@ void __init tcp_init(void) sysctl_tcp_max_orphans >>= (3 - order); sysctl_max_syn_backlog = 128; } - tcp_hashinfo.port_rover = sysctl_local_port_range[0] - 1; sysctl_tcp_mem[0] = 768 << order; sysctl_tcp_mem[1] = 1024 << order; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c85819d8474b..49d67cd75edd 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -93,8 +93,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { .lhash_lock = RW_LOCK_UNLOCKED, .lhash_users = ATOMIC_INIT(0), .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), - .portalloc_lock = SPIN_LOCK_UNLOCKED, - .port_rover = 1024 - 1, }; static int tcp_v4_get_port(struct sock *sk, unsigned short snum) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d693cb988b78..d746d3b27efb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -114,16 +114,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; int remaining = (high - low) + 1; - int rover; + int rover = net_random() % (high - low) + low; - spin_lock(&tcp_hashinfo.portalloc_lock); - if (tcp_hashinfo.port_rover < low) - rover = low; - else - rover = tcp_hashinfo.port_rover; - do { rover++; - if (rover > high) - rover = low; + do { head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) @@ -132,9 +125,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) break; next: spin_unlock(&head->lock); + if (++rover > high) + rover = low; } while (--remaining > 0); - tcp_hashinfo.port_rover = rover; - spin_unlock(&tcp_hashinfo.portalloc_lock); /* Exhausted local port range during search? It is not * possible for us to be holding one of the bind hash -- cgit v1.2.3 From 5b0c76ad94faf95ca50fa0de9ab07460bea19568 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:45:49 -0800 Subject: [PATCH] bnx2: add 5708 support Add 5708 copper and serdes basic support, including 2.5 Gbps support on 5708 serdes. SPEED_2500 is also added to ethtool.h Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 217 ++++++++++++++++++++++++++++++++++++++++++------ drivers/net/bnx2.h | 63 +++++++++++++- include/linux/ethtool.h | 3 +- include/linux/pci_ids.h | 2 + 4 files changed, 256 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 11d252318221..671393a18469 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -41,6 +41,8 @@ typedef enum { NC370I, BCM5706S, NC370F, + BCM5708, + BCM5708S, } board_t; /* indexed by board_t, above */ @@ -52,6 +54,8 @@ static struct { { "HP NC370i Multifunction Gigabit Server Adapter" }, { "Broadcom NetXtreme II BCM5706 1000Base-SX" }, { "HP NC370F Multifunction Gigabit Server Adapter" }, + { "Broadcom NetXtreme II BCM5708 1000Base-T" }, + { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, }; static struct pci_device_id bnx2_pci_tbl[] = { @@ -61,10 +65,14 @@ static struct pci_device_id bnx2_pci_tbl[] = { PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, { 0, } }; @@ -430,6 +438,18 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) return; } + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (CHIP_NUM(bp) == CHIP_NUM_5708)) { + u32 val; + + bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); + if (val & BCM5708S_1000X_STAT1_TX_PAUSE) + bp->flow_ctrl |= FLOW_CTRL_TX; + if (val & BCM5708S_1000X_STAT1_RX_PAUSE) + bp->flow_ctrl |= FLOW_CTRL_RX; + return; + } + bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); bnx2_read_phy(bp, MII_LPA, &remote_adv); @@ -476,7 +496,36 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) } static int -bnx2_serdes_linkup(struct bnx2 *bp) +bnx2_5708s_linkup(struct bnx2 *bp) +{ + u32 val; + + bp->link_up = 1; + bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); + switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) { + case BCM5708S_1000X_STAT1_SPEED_10: + bp->line_speed = SPEED_10; + break; + case BCM5708S_1000X_STAT1_SPEED_100: + bp->line_speed = SPEED_100; + break; + case BCM5708S_1000X_STAT1_SPEED_1G: + bp->line_speed = SPEED_1000; + break; + case BCM5708S_1000X_STAT1_SPEED_2G5: + bp->line_speed = SPEED_2500; + break; + } + if (val & BCM5708S_1000X_STAT1_FD) + bp->duplex = DUPLEX_FULL; + else + bp->duplex = DUPLEX_HALF; + + return 0; +} + +static int +bnx2_5706s_linkup(struct bnx2 *bp) { u32 bmcr, local_adv, remote_adv, common; @@ -593,13 +642,27 @@ bnx2_set_mac_link(struct bnx2 *bp) val = REG_RD(bp, BNX2_EMAC_MODE); val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | - BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK); + BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | + BNX2_EMAC_MODE_25G); if (bp->link_up) { - if (bp->line_speed != SPEED_1000) - val |= BNX2_EMAC_MODE_PORT_MII; - else - val |= BNX2_EMAC_MODE_PORT_GMII; + switch (bp->line_speed) { + case SPEED_10: + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + val |= BNX2_EMAC_MODE_PORT_MII_10; + break; + } + /* fall through */ + case SPEED_100: + val |= BNX2_EMAC_MODE_PORT_MII; + break; + case SPEED_2500: + val |= BNX2_EMAC_MODE_25G; + /* fall through */ + case SPEED_1000: + val |= BNX2_EMAC_MODE_PORT_GMII; + break; + } } else { val |= BNX2_EMAC_MODE_PORT_GMII; @@ -662,7 +725,10 @@ bnx2_set_link(struct bnx2 *bp) bp->link_up = 1; if (bp->phy_flags & PHY_SERDES_FLAG) { - bnx2_serdes_linkup(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5706) + bnx2_5706s_linkup(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + bnx2_5708s_linkup(bp); } else { bnx2_copper_linkup(bp); @@ -755,39 +821,61 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) static int bnx2_setup_serdes_phy(struct bnx2 *bp) { - u32 adv, bmcr; + u32 adv, bmcr, up1; u32 new_adv = 0; if (!(bp->autoneg & AUTONEG_SPEED)) { u32 new_bmcr; + int force_link_down = 0; + + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + if (up1 & BCM5708S_UP1_2G5) { + up1 &= ~BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + force_link_down = 1; + } + } + + bnx2_read_phy(bp, MII_ADVERTISE, &adv); + adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); bnx2_read_phy(bp, MII_BMCR, &bmcr); new_bmcr = bmcr & ~BMCR_ANENABLE; new_bmcr |= BMCR_SPEED1000; if (bp->req_duplex == DUPLEX_FULL) { + adv |= ADVERTISE_1000XFULL; new_bmcr |= BMCR_FULLDPLX; } else { + adv |= ADVERTISE_1000XHALF; new_bmcr &= ~BMCR_FULLDPLX; } - if (new_bmcr != bmcr) { + if ((new_bmcr != bmcr) || (force_link_down)) { /* Force a link down visible on the other side */ if (bp->link_up) { - bnx2_read_phy(bp, MII_ADVERTISE, &adv); - adv &= ~(ADVERTISE_1000XFULL | - ADVERTISE_1000XHALF); - bnx2_write_phy(bp, MII_ADVERTISE, adv); + bnx2_write_phy(bp, MII_ADVERTISE, adv & + ~(ADVERTISE_1000XFULL | + ADVERTISE_1000XHALF)); bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); bp->link_up = 0; netif_carrier_off(bp->dev); + bnx2_write_phy(bp, MII_BMCR, new_bmcr); } + bnx2_write_phy(bp, MII_ADVERTISE, adv); bnx2_write_phy(bp, MII_BMCR, new_bmcr); } return 0; } + if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + up1 |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + } + if (bp->advertising & ADVERTISED_1000baseT_Full) new_adv |= ADVERTISE_1000XFULL; @@ -952,7 +1040,60 @@ bnx2_setup_phy(struct bnx2 *bp) } static int -bnx2_init_serdes_phy(struct bnx2 *bp) +bnx2_init_5708s_phy(struct bnx2 *bp) +{ + u32 val; + + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3); + bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); + + bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val); + val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN; + bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val); + + bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val); + val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN; + bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val); + + if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { + bnx2_read_phy(bp, BCM5708S_UP1, &val); + val |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, val); + } + + if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || + (CHIP_ID(bp) == CHIP_ID_5708_B0)) { + /* increase tx signal amplitude */ + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_TX_MISC); + bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val); + val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM; + bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); + } + + val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_CONFIG) & + BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK; + + if (val) { + u32 is_backplane; + + is_backplane = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_SHARED_HW_CFG_CONFIG); + if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) { + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_TX_MISC); + bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_DIG); + } + } + return 0; +} + +static int +bnx2_init_5706s_phy(struct bnx2 *bp) { bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; @@ -990,6 +1131,8 @@ bnx2_init_serdes_phy(struct bnx2 *bp) static int bnx2_init_copper_phy(struct bnx2 *bp) { + u32 val; + bp->phy_flags |= PHY_CRC_FIX_FLAG; if (bp->phy_flags & PHY_CRC_FIX_FLAG) { @@ -1004,8 +1147,6 @@ bnx2_init_copper_phy(struct bnx2 *bp) } if (bp->dev->mtu > 1500) { - u32 val; - /* Set extended packet length bit */ bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); @@ -1015,8 +1156,6 @@ bnx2_init_copper_phy(struct bnx2 *bp) bnx2_write_phy(bp, 0x10, val | 0x1); } else { - u32 val; - bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); bnx2_write_phy(bp, 0x18, val & ~0x4007); @@ -1025,6 +1164,10 @@ bnx2_init_copper_phy(struct bnx2 *bp) bnx2_write_phy(bp, 0x10, val & ~0x1); } + /* ethernet@wirespeed */ + bnx2_write_phy(bp, 0x18, 0x7007); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4)); return 0; } @@ -1048,7 +1191,10 @@ bnx2_init_phy(struct bnx2 *bp) bp->phy_id |= val & 0xffff; if (bp->phy_flags & PHY_SERDES_FLAG) { - rc = bnx2_init_serdes_phy(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5706) + rc = bnx2_init_5706s_phy(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + rc = bnx2_init_5708s_phy(bp); } else { rc = bnx2_init_copper_phy(bp); @@ -3234,7 +3380,7 @@ bnx2_test_registers(struct bnx2 *bp) { 0x1408, 0, 0x01c00800, 0x00000000 }, { 0x149c, 0, 0x8000ffff, 0x00000000 }, { 0x14a8, 0, 0x00000000, 0x000001ff }, - { 0x14ac, 0, 0x4fffffff, 0x10000000 }, + { 0x14ac, 0, 0x0fffffff, 0x10000000 }, { 0x14b0, 0, 0x00000002, 0x00000001 }, { 0x14b8, 0, 0x00000000, 0x00000000 }, { 0x14c0, 0, 0x00000000, 0x00000009 }, @@ -3577,7 +3723,7 @@ bnx2_test_memory(struct bnx2 *bp) u32 len; } mem_tbl[] = { { 0x60000, 0x4000 }, - { 0xa0000, 0x4000 }, + { 0xa0000, 0x3000 }, { 0xe0000, 0x4000 }, { 0x120000, 0x4000 }, { 0x1a0000, 0x4000 }, @@ -4264,7 +4410,8 @@ bnx2_get_stats(struct net_device *dev) (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions + stats_blk->stat_Dot3StatsLateCollisions); - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if ((CHIP_NUM(bp) == CHIP_NUM_5706) || + (CHIP_ID(bp) == CHIP_ID_5708_A0)) net_stats->tx_carrier_errors = 0; else { net_stats->tx_carrier_errors = @@ -4814,6 +4961,14 @@ static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = { 4,4,4,4,4, }; +static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = { + 8,0,8,8,8,8,8,8,8,8, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4, +}; + #define BNX2_NUM_TESTS 6 static struct { @@ -4922,8 +5077,13 @@ bnx2_get_ethtool_stats(struct net_device *dev, return; } - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || + (CHIP_ID(bp) == CHIP_ID_5706_A1) || + (CHIP_ID(bp) == CHIP_ID_5706_A2) || + (CHIP_ID(bp) == CHIP_ID_5708_A0)) stats_len_arr = bnx2_5706_stats_len_arr; + else + stats_len_arr = bnx2_5708_stats_len_arr; for (i = 0; i < BNX2_NUM_STATS; i++) { if (stats_len_arr[i] == 0) { @@ -5205,8 +5365,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->chip_id = REG_RD(bp, BNX2_MISC_ID); - bp->phy_addr = 1; - /* Get bus information. */ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { @@ -5316,10 +5474,19 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->timer_interval = HZ; bp->current_interval = HZ; + bp->phy_addr = 1; + /* Disable WOL support if we are running on a SERDES chip. */ if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) { bp->phy_flags |= PHY_SERDES_FLAG; bp->flags |= NO_WOL_FLAG; + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bp->phy_addr = 2; + reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_SHARED_HW_CFG_CONFIG); + if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) + bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; + } } if (CHIP_ID(bp) == CHIP_ID_5706_A0) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 62857b6a6ee4..c0e88f850493 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -1449,8 +1449,9 @@ struct l2_fhdr { #define BNX2_EMAC_MODE_PORT_NONE (0L<<2) #define BNX2_EMAC_MODE_PORT_MII (1L<<2) #define BNX2_EMAC_MODE_PORT_GMII (2L<<2) -#define BNX2_EMAC_MODE_PORT_UNDEF (3L<<2) +#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2) #define BNX2_EMAC_MODE_MAC_LOOP (1L<<4) +#define BNX2_EMAC_MODE_25G (1L<<5) #define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7) #define BNX2_EMAC_MODE_TX_BURST (1L<<8) #define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9) @@ -3724,6 +3725,53 @@ struct l2_fhdr { #define PHY_ID(id) ((id) & 0xfffffff0) #define PHY_REV_ID(id) ((id) & 0xf) +/* 5708 Serdes PHY registers */ + +#define BCM5708S_UP1 0xb + +#define BCM5708S_UP1_2G5 0x1 + +#define BCM5708S_BLK_ADDR 0x1f + +#define BCM5708S_BLK_ADDR_DIG 0x0000 +#define BCM5708S_BLK_ADDR_DIG3 0x0002 +#define BCM5708S_BLK_ADDR_TX_MISC 0x0005 + +/* Digital Block */ +#define BCM5708S_1000X_CTL1 0x10 + +#define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001 +#define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010 + +#define BCM5708S_1000X_CTL2 0x11 + +#define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001 + +#define BCM5708S_1000X_STAT1 0x14 + +#define BCM5708S_1000X_STAT1_SGMII 0x0001 +#define BCM5708S_1000X_STAT1_LINK 0x0002 +#define BCM5708S_1000X_STAT1_FD 0x0004 +#define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018 +#define BCM5708S_1000X_STAT1_SPEED_10 0x0000 +#define BCM5708S_1000X_STAT1_SPEED_100 0x0008 +#define BCM5708S_1000X_STAT1_SPEED_1G 0x0010 +#define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018 +#define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020 +#define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040 + +/* Digital3 Block */ +#define BCM5708S_DIG_3_0 0x10 + +#define BCM5708S_DIG_3_0_USE_IEEE 0x0001 + +/* Tx/Misc Block */ +#define BCM5708S_TX_ACTL1 0x15 + +#define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30 + +#define BCM5708S_TX_ACTL3 0x17 + #define MIN_ETHERNET_PACKET_SIZE 60 #define MAX_ETHERNET_PACKET_SIZE 1514 #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014 @@ -3893,6 +3941,7 @@ struct bnx2 { #define PHY_SERDES_FLAG 1 #define PHY_CRC_FIX_FLAG 2 #define PHY_PARALLEL_DETECT_FLAG 4 +#define PHY_2_5G_CAPABLE_FLAG 8 #define PHY_INT_MODE_MASK_FLAG 0x300 #define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 #define PHY_INT_MODE_LINK_READY_FLAG 0x200 @@ -3901,6 +3950,7 @@ struct bnx2 { /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */ #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) #define CHIP_NUM_5706 0x57060000 +#define CHIP_NUM_5708 0x57080000 #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) #define CHIP_REV_Ax 0x00000000 @@ -3913,6 +3963,9 @@ struct bnx2 { #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) #define CHIP_ID_5706_A0 0x57060000 #define CHIP_ID_5706_A1 0x57060010 +#define CHIP_ID_5706_A2 0x57060020 +#define CHIP_ID_5708_A0 0x57080000 +#define CHIP_ID_5708_B0 0x57081000 #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) @@ -4132,12 +4185,12 @@ struct fw_info { #define BNX2_LINK_STATUS 0x0000000c #define BNX2_DRV_PULSE_MB 0x00000010 -#define BNX2_DRV_PULSE_SEQ_MASK 0x0000ffff +#define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff /* Indicate to the firmware not to go into the * OS absent when it is not getting driver pulse. * This is used for debugging. */ -#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00010000 +#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000 #define BNX2_DEV_INFO_SIGNATURE 0x00000020 #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 @@ -4160,6 +4213,8 @@ struct fw_info { #define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1 #define BNX2_SHARED_HW_CFG_PHY_COPPER 0 #define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2 +#define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20 +#define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40 #define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8 #define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300 #define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0 @@ -4173,9 +4228,11 @@ struct fw_info { #define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054 #define BNX2_PORT_HW_CFG_CONFIG 0x00000058 +#define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000 #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000 #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000 +#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000 #define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068 #define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index d2c390eff1b2..93535f093216 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -453,10 +453,11 @@ struct ethtool_ops { * it was foced up into this mode or autonegotiated. */ -/* The forced speed, 10Mb, 100Mb, gigabit, 10GbE. */ +/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 +#define SPEED_2500 2500 #define SPEED_10000 10000 /* Duplex, half or full. */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 88de3f8ce1a2..8cadfdeef674 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1785,6 +1785,7 @@ #define PCI_DEVICE_ID_TIGON3_5704 0x1648 #define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 #define PCI_DEVICE_ID_NX2_5706 0x164a +#define PCI_DEVICE_ID_NX2_5708 0x164c #define PCI_DEVICE_ID_TIGON3_5702FE 0x164d #define PCI_DEVICE_ID_TIGON3_5705 0x1653 #define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 @@ -1809,6 +1810,7 @@ #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_5706S 0x16aa +#define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5781 0x16dd -- cgit v1.2.3 From 21c614a7899046ab108b3d327d76c33443a8ebf2 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sun, 6 Nov 2005 09:07:03 +0000 Subject: [SERIAL] Support Au1x00 8250 UARTs using the generic 8250 driver. The offsets of the registers are in a different place, and some parts cannot handle a full set of modem control signals. Signed-off-by: Pantelis Antoniou Signed-off-by: Russell King --- drivers/serial/8250.c | 73 +++++++++++++++++++++++++++++-- drivers/serial/8250.h | 1 + drivers/serial/8250_au1x00.c | 102 +++++++++++++++++++++++++++++++++++++++++++ drivers/serial/Kconfig | 8 ++++ drivers/serial/Makefile | 1 + drivers/serial/serial_core.c | 1 + include/linux/serial_8250.h | 1 + include/linux/serial_core.h | 1 + 8 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 drivers/serial/8250_au1x00.c (limited to 'include') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index f47d2c454e33..186e96c47b3d 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -251,9 +251,53 @@ static const struct serial8250_config uart_config[] = { }, }; +#ifdef CONFIG_SERIAL_8250_AU1X00 + +/* Au1x00 UART hardware has a weird register layout */ +static const u8 au_io_in_map[] = { + [UART_RX] = 0, + [UART_IER] = 2, + [UART_IIR] = 3, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = 7, + [UART_MSR] = 8, +}; + +static const u8 au_io_out_map[] = { + [UART_TX] = 1, + [UART_IER] = 2, + [UART_FCR] = 4, + [UART_LCR] = 5, + [UART_MCR] = 6, +}; + +/* sane hardware needs no mapping */ +static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_in_map[offset]; +} + +static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_out_map[offset]; +} + +#else + +/* sane hardware needs no mapping */ +#define map_8250_in_reg(up, offset) (offset) +#define map_8250_out_reg(up, offset) (offset) + +#endif + static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) { - offset <<= up->port.regshift; + offset = map_8250_in_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -266,6 +310,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) case UPIO_MEM32: return readl(up->port.membase + offset); +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + return __raw_readl(up->port.membase + offset); +#endif + default: return inb(up->port.iobase + offset); } @@ -274,7 +323,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) static _INLINE_ void serial_out(struct uart_8250_port *up, int offset, int value) { - offset <<= up->port.regshift; + offset = map_8250_out_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -290,6 +339,12 @@ serial_out(struct uart_8250_port *up, int offset, int value) writel(value, up->port.membase + offset); break; +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + __raw_writel(value, up->port.membase + offset); + break; +#endif + default: outb(value, up->port.iobase + offset); } @@ -910,6 +965,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) } } #endif + +#ifdef CONFIG_SERIAL_8250_AU1X00 + /* if access method is AU, it is a 16550 with a quirk */ + if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; +#endif + serial_outp(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { @@ -1057,6 +1119,10 @@ static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); } @@ -1774,7 +1840,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, * CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (!(up->bugs & UART_BUG_NOMSR) && + UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; if (up->capabilities & UART_CAP_UUE) up->ier |= UART_IER_UUE | UART_IER_RTOIE; diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index b1b459efda52..a607b98016db 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -49,6 +49,7 @@ struct serial8250_config { #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ +#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) #define _INLINE_ inline diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c new file mode 100644 index 000000000000..06ae8fbcc947 --- /dev/null +++ b/drivers/serial/8250_au1x00.c @@ -0,0 +1,102 @@ +/* + * Serial Device Initialisation for Au1x00 + * + * (C) Copyright Embedded Alley Solutions, Inc 2005 + * Author: Pantelis Antoniou + * + * 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 +#include +#include +#include +#include + +#include + +#include + +#include "8250.h" + +#define PORT(_base, _irq) \ + { \ + .iobase = _base, \ + .membase = (void __iomem *)_base,\ + .mapbase = _base, \ + .irq = _irq, \ + .uartclk = 0, /* filled */ \ + .regshift = 2, \ + .iotype = UPIO_AU, \ + .flags = UPF_SKIP_TEST | \ + UPF_IOREMAP, \ + } + +static struct plat_serial8250_port au1x00_data[] = { +#if defined(CONFIG_SOC_AU1000) + PORT(UART0_ADDR, AU1000_UART0_INT), + PORT(UART1_ADDR, AU1000_UART1_INT), + PORT(UART2_ADDR, AU1000_UART2_INT), + PORT(UART3_ADDR, AU1000_UART3_INT), +#elif defined(CONFIG_SOC_AU1500) + PORT(UART0_ADDR, AU1500_UART0_INT), + PORT(UART3_ADDR, AU1500_UART3_INT), +#elif defined(CONFIG_SOC_AU1100) + PORT(UART0_ADDR, AU1100_UART0_INT), + PORT(UART1_ADDR, AU1100_UART1_INT), + PORT(UART2_ADDR, AU1100_UART2_INT), + PORT(UART3_ADDR, AU1100_UART3_INT), +#elif defined(CONFIG_SOC_AU1550) + PORT(UART0_ADDR, AU1550_UART0_INT), + PORT(UART1_ADDR, AU1550_UART1_INT), + PORT(UART2_ADDR, AU1550_UART2_INT), + PORT(UART3_ADDR, AU1550_UART3_INT), +#elif defined(CONFIG_SOC_AU1200) + PORT(UART0_ADDR, AU1200_UART0_INT), + PORT(UART1_ADDR, AU1200_UART1_INT), +#endif + { }, +}; + +static struct platform_device au1x00_device = { + .name = "serial8250", + .id = PLAT8250_DEV_AU1X00, + .dev = { + .platform_data = au1x00_data, + }, +}; + +static int __init au1x00_init(void) +{ + int i; + unsigned int uartclk; + + /* get uart clock */ + uartclk = get_au1x00_uart_baud_base() * 16; + + /* fill up uartclk */ + for (i = 0; au1x00_data[i].flags ; i++) + au1x00_data[i].uartclk = uartclk; + + return platform_device_register(&au1x00_device); +} + +/* XXX: Yes, I know this doesn't yet work. */ +static void __exit au1x00_exit(void) +{ + platform_device_unregister(&au1x00_device); +} + +module_init(au1x00_init); +module_exit(au1x00_exit); + +MODULE_AUTHOR("Pantelis Antoniou "); +MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b745a1b9e835..ff36f0c9fdad 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -207,6 +207,14 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AU1X00 + bool "AU1X00 serial port support" + depends on SERIAL_8250 != n && SOC_AU1X00 + help + If you have an Au1x00 board and want to use the serial port, say Y + to this option. The driver can handle 1 or 2 serial ports. + If unsure, say N. + comment "Non-8250 serial port support" config SERIAL_AMBA_PL010 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 11c7dc483f93..d7c7c7180e33 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0745ce782974..427a23858076 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1959,6 +1959,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) break; case UPIO_MEM: case UPIO_MEM32: + case UPIO_AU: snprintf(address, sizeof(address), "MMIO 0x%lx", port->mapbase); break; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 2b799d40d669..cee302aefdb7 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -42,6 +42,7 @@ enum { PLAT8250_DEV_BOCA, PLAT8250_DEV_HUB6, PLAT8250_DEV_MCA, + PLAT8250_DEV_AU1X00, }; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9d2579230689..a3ac92b19aca 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -211,6 +211,7 @@ struct uart_port { #define UPIO_HUB6 (1) #define UPIO_MEM (2) #define UPIO_MEM32 (3) +#define UPIO_AU (4) /* Au1x00 type IO */ unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ -- cgit v1.2.3 From 2dd34b488a99135ad2a529e33087ddd6a09e992a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 30 Oct 2005 22:42:11 +0100 Subject: [PATCH] kbuild: permanently fix kernel configuration include mess Include autoconf.h into every kernel compilation via the gcc command line using -imacros. This ensures that we have the kernel configuration included from the start, rather than relying on each file having #include as appropriate. History has shown that this is something which is difficult to get right. Since we now include the kernel configuration automatically, make configcheck becomes meaningless, so remove it. Signed-off-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg --- Makefile | 8 ++------ include/linux/config.h | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/Makefile b/Makefile index 79601320ac3e..2dac8010c142 100644 --- a/Makefile +++ b/Makefile @@ -346,7 +346,8 @@ AFLAGS_KERNEL = # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option LINUXINCLUDE := -Iinclude \ - $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) + $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ + -imacros include/linux/autoconf.h CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) @@ -1249,11 +1250,6 @@ tags: FORCE # Scripts to check various things for consistency # --------------------------------------------------------------------------- -configcheck: - find * $(RCS_FIND_IGNORE) \ - -name '*.[hcS]' -type f -print | sort \ - | xargs $(PERL) -w scripts/checkconfig.pl - includecheck: find * $(RCS_FIND_IGNORE) \ -name '*.[hcS]' -type f -print | sort \ diff --git a/include/linux/config.h b/include/linux/config.h index 9d1c14f7ad6d..a91f5e55b525 100644 --- a/include/linux/config.h +++ b/include/linux/config.h @@ -1,6 +1,8 @@ #ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H - +/* This file is no longer in use and kept only for backward compatibility. + * autoconf.h is now included via -imacros on the commandline + */ #include #endif -- cgit v1.2.3 From 8459c159f7de832eaf888398d2abf466c388dfa6 Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Sun, 6 Nov 2005 14:27:52 +0000 Subject: [ARM] 3088/1: PXA: Add machine support for the Sharp SL-6000x series of PDAs Patch from Dirk Opfer This patch adds basic machine support for the Sharp SL-6000x (Tosa) PDAs. Signed-off-by: Dirk Opfer Signed-off-by: Richard Purdie Signed-off-by: Russell King --- MAINTAINERS | 5 ++ arch/arm/mach-pxa/Kconfig | 9 ++- arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/tosa.c | 162 +++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/tosa.h | 166 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-pxa/tosa.c create mode 100644 include/asm-arm/arch-pxa/tosa.h (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index 983f9e9aed61..23337f88c508 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -297,6 +297,11 @@ P: Richard Purdie M: rpurdie@rpsys.net S: Maintained +ARM/TOSA MACHINE SUPPORT +P: Dirk Opfer +M: dirk@opfer-online.de +S: Maintained + ARM/PLEB SUPPORT P: Peter Chubb M: pleb@gelato.unsw.edu.au diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 3e5f69bb5ac4..b380a438e68f 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -27,7 +27,8 @@ config PXA_SHARPSL Say Y here if you intend to run this kernel on a Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita), - SL-C3000 (Spitz) or SL-C3100 (Borzoi) handheld computer. + SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa) + handheld computer. endchoice @@ -37,7 +38,7 @@ choice prompt "Select target Sharp Zaurus device range" config PXA_SHARPSL_25x - bool "Sharp PXA25x models (SL-5600 and SL-C7xx)" + bool "Sharp PXA25x models (SL-5600, SL-C7xx and SL-C6000x)" select PXA25x config PXA_SHARPSL_27x @@ -80,6 +81,10 @@ config MACH_BORZOI depends PXA_SHARPSL_27x select PXA_SHARP_Cxx00 +config MACH_TOSA + bool "Enable Sharp SL-6000x (Tosa) Support" + depends PXA_SHARPSL + config PXA25x bool help diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index f609a0f232cb..8bc72d07cea8 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o obj-$(CONFIG_MACH_POODLE) += poodle.o +obj-$(CONFIG_MACH_TOSA) += tosa.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c new file mode 100644 index 000000000000..400609f8b6a8 --- /dev/null +++ b/arch/arm/mach-pxa/tosa.c @@ -0,0 +1,162 @@ +/* + * Support for Sharp SL-C6000x PDAs + * Model: (Tosa) + * + * Copyright (c) 2005 Dirk Opfer + * + * Based on code written by Sharp/Lineo for 2.4 kernels + * + * 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 +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" + + +/* + * SCOOP Device + */ +static struct resource tosa_scoop_resources[] = { + [0] = { + .start = TOSA_CF_PHYS, + .end = TOSA_CF_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct scoop_config tosa_scoop_setup = { + .io_dir = TOSA_SCOOP_IO_DIR, + .io_out = TOSA_SCOOP_IO_OUT, + +}; + +struct platform_device tosascoop_device = { + .name = "sharp-scoop", + .id = 0, + .dev = { + .platform_data = &tosa_scoop_setup, + }, + .num_resources = ARRAY_SIZE(tosa_scoop_resources), + .resource = tosa_scoop_resources, +}; + + +/* + * SCOOP Device Jacket + */ +static struct resource tosa_scoop_jc_resources[] = { + [0] = { + .start = TOSA_SCOOP_PHYS + 0x40, + .end = TOSA_SCOOP_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct scoop_config tosa_scoop_jc_setup = { + .io_dir = TOSA_SCOOP_JC_IO_DIR, + .io_out = TOSA_SCOOP_JC_IO_OUT, +}; + +struct platform_device tosascoop_jc_device = { + .name = "sharp-scoop", + .id = 1, + .dev = { + .platform_data = &tosa_scoop_jc_setup, + .parent = &tosascoop_device.dev, + }, + .num_resources = ARRAY_SIZE(tosa_scoop_jc_resources), + .resource = tosa_scoop_jc_resources, +}; + +static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = { +{ + .dev = &tosascoop_device.dev, + .irq = TOSA_IRQ_GPIO_CF_IRQ, + .cd_irq = TOSA_IRQ_GPIO_CF_CD, + .cd_irq_str = "PCMCIA0 CD", +},{ + .dev = &tosascoop_jc_device.dev, + .irq = TOSA_IRQ_GPIO_JC_CF_IRQ, + .cd_irq = -1, +}, +}; + + +static struct platform_device *devices[] __initdata = { + &tosascoop_device, + &tosascoop_jc_device, +}; + +static void __init tosa_init(void) +{ + pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN); + pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN); + + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00000000; + PGSR1 = 0x00FF0002; + PGSR2 = 0x00014000; + PCFR |= PCFR_OPDE; + + // enable batt_fault + PMCR = 0x01; + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + scoop_num = 2; + scoop_devs = &tosa_pcmcia_scoop[0]; +} + +static void __init fixup_tosa(struct machine_desc *desc, + struct tag *tags, char **cmdline, struct meminfo *mi) +{ + sharpsl_save_param(); + mi->nr_banks=1; + mi->bank[0].start = 0xa0000000; + mi->bank[0].node = 0; + mi->bank[0].size = (64*1024*1024); +} + +MACHINE_START(TOSA, "SHARP Tosa") + .phys_ram = 0xa0000000, + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .fixup = fixup_tosa, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, + .init_machine = tosa_init, + .timer = &pxa_timer, +MACHINE_END diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h new file mode 100644 index 000000000000..c3364a2c4758 --- /dev/null +++ b/include/asm-arm/arch-pxa/tosa.h @@ -0,0 +1,166 @@ +/* + * Hardware specific definitions for Sharp SL-C6000x series of PDAs + * + * Copyright (c) 2005 Dirk Opfer + * + * Based on Sharp's 2.4 kernel patches + * + * 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. + * + */ +#ifndef _ASM_ARCH_TOSA_H_ +#define _ASM_ARCH_TOSA_H_ 1 + +/* TOSA Chip selects */ +#define TOSA_LCDC_PHYS PXA_CS4_PHYS +/* Internel Scoop */ +#define TOSA_CF_PHYS (PXA_CS2_PHYS + 0x00800000) +/* Jacket Scoop */ +#define TOSA_SCOOP_PHYS (PXA_CS5_PHYS + 0x00800000) + +/* + * SCOOP2 internal GPIOs + */ +#define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11 +#define TOSA_SCOOP_TC6393_REST_IN SCOOP_GPCR_PA12 +#define TOSA_SCOOP_IR_POWERDWN SCOOP_GPCR_PA13 +#define TOSA_SCOOP_SD_WP SCOOP_GPCR_PA14 +#define TOSA_SCOOP_PWR_ON SCOOP_GPCR_PA15 +#define TOSA_SCOOP_AUD_PWR_ON SCOOP_GPCR_PA16 +#define TOSA_SCOOP_BT_RESET SCOOP_GPCR_PA17 +#define TOSA_SCOOP_BT_PWR_EN SCOOP_GPCR_PA18 +#define TOSA_SCOOP_AC_IN_OL SCOOP_GPCR_PA19 + +/* GPIO Direction 1 : output mode / 0:input mode */ +#define TOSA_SCOOP_IO_DIR ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \ + TOSA_SCOOP_IR_POWERDWN | TOSA_SCOOP_PWR_ON | TOSA_SCOOP_AUD_PWR_ON |\ + TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN ) +/* GPIO out put level when init 1: Hi */ +#define TOSA_SCOOP_IO_OUT ( TOSA_SCOOP_TC6393_REST_IN ) + +/* + * SCOOP2 jacket GPIOs + */ +#define TOSA_SCOOP_JC_BT_LED SCOOP_GPCR_PA11 +#define TOSA_SCOOP_JC_NOTE_LED SCOOP_GPCR_PA12 +#define TOSA_SCOOP_JC_CHRG_ERR_LED SCOOP_GPCR_PA13 +#define TOSA_SCOOP_JC_USB_PULLUP SCOOP_GPCR_PA14 +#define TOSA_SCOOP_JC_TC6393_SUSPEND SCOOP_GPCR_PA15 +#define TOSA_SCOOP_JC_TC3693_L3V_ON SCOOP_GPCR_PA16 +#define TOSA_SCOOP_JC_WLAN_DETECT SCOOP_GPCR_PA17 +#define TOSA_SCOOP_JC_WLAN_LED SCOOP_GPCR_PA18 +#define TOSA_SCOOP_JC_CARD_LIMIT_SEL SCOOP_GPCR_PA19 + +/* GPIO Direction 1 : output mode / 0:input mode */ +#define TOSA_SCOOP_JC_IO_DIR ( TOSA_SCOOP_JC_BT_LED | TOSA_SCOOP_JC_NOTE_LED | \ + TOSA_SCOOP_JC_CHRG_ERR_LED | TOSA_SCOOP_JC_USB_PULLUP | \ + TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \ + TOSA_SCOOP_JC_WLAN_LED | TOSA_SCOOP_JC_CARD_LIMIT_SEL ) +/* GPIO out put level when init 1: Hi */ +#define TOSA_SCOOP_JC_IO_OUT ( 0 ) + +/* + * Timing Generator + */ +#define TG_PNLCTL 0x00 +#define TG_TPOSCTL 0x01 +#define TG_DUTYCTL 0x02 +#define TG_GPOSR 0x03 +#define TG_GPODR1 0x04 +#define TG_GPODR2 0x05 +#define TG_PINICTL 0x06 +#define TG_HPOSCTL 0x07 + +/* + * LED + */ +#define TOSA_SCOOP_LED_BLUE TOSA_SCOOP_GPCR_PA11 +#define TOSA_SCOOP_LED_GREEN TOSA_SCOOP_GPCR_PA12 +#define TOSA_SCOOP_LED_ORANGE TOSA_SCOOP_GPCR_PA13 +#define TOSA_SCOOP_LED_WLAN TOSA_SCOOP_GPCR_PA18 + + +/* + * PXA GPIOs + */ +#define TOSA_GPIO_POWERON (0) +#define TOSA_GPIO_RESET (1) +#define TOSA_GPIO_AC_IN (2) +#define TOSA_GPIO_RECORD_BTN (3) +#define TOSA_GPIO_SYNC (4) /* Cradle SYNC Button */ +#define TOSA_GPIO_USB_IN (5) +#define TOSA_GPIO_JACKET_DETECT (7) +#define TOSA_GPIO_nSD_DETECT (9) +#define TOSA_GPIO_nSD_INT (10) +#define TOSA_GPIO_TC6393_CLK (11) +#define TOSA_GPIO_BAT1_CRG (12) +#define TOSA_GPIO_CF_CD (13) +#define TOSA_GPIO_BAT0_CRG (14) +#define TOSA_GPIO_TC6393_INT (15) +#define TOSA_GPIO_BAT0_LOW (17) +#define TOSA_GPIO_TC6393_RDY (18) +#define TOSA_GPIO_ON_RESET (19) +#define TOSA_GPIO_EAR_IN (20) +#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */ +#define TOSA_GPIO_ON_KEY (22) +#define TOSA_GPIO_VGA_LINE (27) +#define TOSA_GPIO_TP_INT (32) /* Touch Panel pen down interrupt */ +#define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */ +#define TOSA_GPIO_BAT_LOCKED (38) /* Battery locked */ +#define TOSA_GPIO_TG_SPI_SCLK (81) +#define TOSA_GPIO_TG_SPI_CS (82) +#define TOSA_GPIO_TG_SPI_MOSI (83) +#define TOSA_GPIO_BAT1_LOW (84) + +#define TOSA_GPIO_HP_IN GPIO_EAR_IN + +#define TOSA_GPIO_MAIN_BAT_LOW GPIO_BAT0_LOW + +#define TOSA_KEY_STROBE_NUM (11) +#define TOSA_KEY_SENSE_NUM (7) + +#define TOSA_GPIO_HIGH_STROBE_BIT (0xfc000000) +#define TOSA_GPIO_LOW_STROBE_BIT (0x0000001f) +#define TOSA_GPIO_ALL_SENSE_BIT (0x00000fe0) +#define TOSA_GPIO_ALL_SENSE_RSHIFT (5) +#define TOSA_GPIO_STROBE_BIT(a) GPIO_bit(58+(a)) +#define TOSA_GPIO_SENSE_BIT(a) GPIO_bit(69+(a)) +#define TOSA_GAFR_HIGH_STROBE_BIT (0xfff00000) +#define TOSA_GAFR_LOW_STROBE_BIT (0x000003ff) +#define TOSA_GAFR_ALL_SENSE_BIT (0x00fffc00) +#define TOSA_GPIO_KEY_SENSE(a) (69+(a)) +#define TOSA_GPIO_KEY_STROBE(a) (58+(a)) + +/* + * Interrupts + */ +#define TOSA_IRQ_GPIO_WAKEUP IRQ_GPIO(TOSA_GPIO_WAKEUP) +#define TOSA_IRQ_GPIO_AC_IN IRQ_GPIO(TOSA_GPIO_AC_IN) +#define TOSA_IRQ_GPIO_RECORD_BTN IRQ_GPIO(TOSA_GPIO_RECORD_BTN) +#define TOSA_IRQ_GPIO_SYNC IRQ_GPIO(TOSA_GPIO_SYNC) +#define TOSA_IRQ_GPIO_USB_IN IRQ_GPIO(TOSA_GPIO_USB_IN) +#define TOSA_IRQ_GPIO_JACKET_DETECT IRQ_GPIO(TOSA_GPIO_JACKET_DETECT) +#define TOSA_IRQ_GPIO_nSD_INT IRQ_GPIO(TOSA_GPIO_nSD_INT) +#define TOSA_IRQ_GPIO_nSD_DETECT IRQ_GPIO(TOSA_GPIO_nSD_DETECT) +#define TOSA_IRQ_GPIO_BAT1_CRG IRQ_GPIO(TOSA_GPIO_BAT1_CRG) +#define TOSA_IRQ_GPIO_CF_CD IRQ_GPIO(TOSA_GPIO_CF_CD) +#define TOSA_IRQ_GPIO_BAT0_CRG IRQ_GPIO(TOSA_GPIO_BAT0_CRG) +#define TOSA_IRQ_GPIO_TC6393_INT IRQ_GPIO(TOSA_GPIO_TC6393_INT) +#define TOSA_IRQ_GPIO_BAT0_LOW IRQ_GPIO(TOSA_GPIO_BAT0_LOW) +#define TOSA_IRQ_GPIO_EAR_IN IRQ_GPIO(TOSA_GPIO_EAR_IN) +#define TOSA_IRQ_GPIO_CF_IRQ IRQ_GPIO(TOSA_GPIO_CF_IRQ) +#define TOSA_IRQ_GPIO_ON_KEY IRQ_GPIO(TOSA_GPIO_ON_KEY) +#define TOSA_IRQ_GPIO_VGA_LINE IRQ_GPIO(TOSA_GPIO_VGA_LINE) +#define TOSA_IRQ_GPIO_TP_INT IRQ_GPIO(TOSA_GPIO_TP_INT) +#define TOSA_IRQ_GPIO_JC_CF_IRQ IRQ_GPIO(TOSA_GPIO_JC_CF_IRQ) +#define TOSA_IRQ_GPIO_BAT_LOCKED IRQ_GPIO(TOSA_GPIO_BAT_LOCKED) +#define TOSA_IRQ_GPIO_BAT1_LOW IRQ_GPIO(TOSA_GPIO_BAT1_LOW) +#define TOSA_IRQ_GPIO_KEY_SENSE(a) IRQ_GPIO(69+(a)) + +#define TOSA_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(TOSA_GPIO_MAIN_BAT_LOW) + +extern struct platform_device tosascoop_jc_device; +extern struct platform_device tosascoop_device; +#endif /* _ASM_ARCH_TOSA_H_ */ -- cgit v1.2.3 From 756c7b748926b0baec6d2a921c3711679282c8fd Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Sun, 6 Nov 2005 15:03:23 +0000 Subject: [ARM] 3113/1: PXA: Allow machines to override (and also reuse) pxa pm functions Patch from Richard Purdie Update the PXA pm.c file to allow machines (such as the Sharp Zaurus) to override the standard pm functions but reuse/wrap them where needed. The init call is made slightly earlier to give machine code an init level to override them in removing any race. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/pm.c | 16 ++++++++++++---- include/asm-arm/arch-pxa/pm.h | 12 ++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 include/asm-arm/arch-pxa/pm.h (limited to 'include') diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index ac4dd4336160..f74b9af112dc 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -72,7 +74,7 @@ enum { SLEEP_SAVE_START = 0, }; -static int pxa_pm_enter(suspend_state_t state) +int pxa_pm_enter(suspend_state_t state) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long checksum = 0; @@ -191,6 +193,8 @@ static int pxa_pm_enter(suspend_state_t state) return 0; } +EXPORT_SYMBOL_GPL(pxa_pm_enter); + unsigned long sleep_phys_sp(void *sp) { return virt_to_phys(sp); @@ -199,21 +203,25 @@ unsigned long sleep_phys_sp(void *sp) /* * Called after processes are frozen, but before we shut down devices. */ -static int pxa_pm_prepare(suspend_state_t state) +int pxa_pm_prepare(suspend_state_t state) { extern int pxa_cpu_pm_prepare(suspend_state_t state); return pxa_cpu_pm_prepare(state); } +EXPORT_SYMBOL_GPL(pxa_pm_prepare); + /* * Called after devices are re-setup, but before processes are thawed. */ -static int pxa_pm_finish(suspend_state_t state) +int pxa_pm_finish(suspend_state_t state) { return 0; } +EXPORT_SYMBOL_GPL(pxa_pm_finish); + /* * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. */ @@ -230,4 +238,4 @@ static int __init pxa_pm_init(void) return 0; } -late_initcall(pxa_pm_init); +device_initcall(pxa_pm_init); diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h new file mode 100644 index 000000000000..7a8a1cdf430d --- /dev/null +++ b/include/asm-arm/arch-pxa/pm.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2005 Richard Purdie + * + * 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. + * + */ + +extern int pxa_pm_prepare(suspend_state_t state); +extern int pxa_pm_enter(suspend_state_t state); +extern int pxa_pm_finish(suspend_state_t state); -- cgit v1.2.3 From 2b79adcca147c9f8fd1094ab4cb342d7e1790d70 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 17 Jul 2005 12:13:51 +0100 Subject: [JFFS2] Use f->target instead of f->dents for symlink target JFFS2 uses f->dents to store the pointer to the symlink target string (in case the inode is symlink). This is somewhat ugly to use the same field for different reasons. Introduce distinct field f->target for this purpose. Note, f->fragtree, f->dents, f->target may probably be put in a union. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/dir.c | 12 ++++++------ fs/jffs2/os-linux.h | 3 ++- fs/jffs2/readinode.c | 45 ++++++++++++++++++++------------------------- fs/jffs2/symlink.c | 26 ++++++++++++-------------- include/linux/jffs2_fs_i.h | 5 ++++- 5 files changed, 44 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 3ca0d25eef1d..5738df223775 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.86 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -344,9 +344,9 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return PTR_ERR(fn); } - /* We use f->dents field to store the target path. */ - f->dents = kmalloc(targetlen + 1, GFP_KERNEL); - if (!f->dents) { + /* We use f->target field to store the target path. */ + f->target = kmalloc(targetlen + 1, GFP_KERNEL); + if (!f->target) { printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); up(&f->sem); jffs2_complete_reservation(c); @@ -354,8 +354,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return -ENOMEM; } - memcpy(f->dents, target, targetlen + 1); - D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->dents)); + memcpy(f->target, target, targetlen + 1); + D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); /* No data here. Only a metadata node, which will be obsoleted by the first data write diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index d900c8929b09..0fc952eaf8c8 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.58 2005/07/12 02:34:35 tpoynor Exp $ + * $Id: os-linux.h,v 1.59 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -57,6 +57,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) f->fragtree = RB_ROOT; f->metadata = NULL; f->dents = NULL; + f->target = NULL; f->flags = 0; f->usercompr = 0; } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index cf39bcf3e3cf..49da1a6cfc81 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.126 2005/07/17 06:56:21 dedekind Exp $ + * $Id: readinode.c,v 1.127 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -547,11 +547,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, if (f->inocache->state != INO_STATE_CHECKING) { /* Symlink's inode data is the target path. Read it and - * keep in RAM to facilitate quick follow symlink operation. - * We use f->dents field to store the target path, which - * is somewhat ugly. */ - f->dents = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); - if (!f->dents) { + * keep in RAM to facilitate quick follow symlink + * operation. */ + f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); + if (!f->target) { printk(KERN_WARNING "Can't allocate %d bytes of memory " "for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); @@ -561,21 +560,21 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), - je32_to_cpu(latest_node->csize), &retlen, (char *)f->dents); + je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; - kfree(f->dents); - f->dents = NULL; + kfree(f->target); + f->target = NULL; up(&f->sem); jffs2_do_clear_inode(c, f); return -ret; } - ((char *)f->dents)[je32_to_cpu(latest_node->csize)] = '\0'; + f->target[je32_to_cpu(latest_node->csize)] = '\0'; D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", - (char *)f->dents)); + f->target)); } /* fall through... */ @@ -638,20 +637,16 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); - /* For symlink inodes we us f->dents to store the target path name */ - if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) { - if (f->dents) { - kfree(f->dents); - f->dents = NULL; - } - } else { - fds = f->dents; - - while(fds) { - fd = fds; - fds = fd->next; - jffs2_free_full_dirent(fd); - } + if (f->target) { + kfree(f->target); + f->target = NULL; + } + + fds = f->dents; + while(fds) { + fd = fds; + fds = fd->next; + jffs2_free_full_dirent(fd); } if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 82ef484f5e12..6fd5ee4f90b7 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.16 2005/03/01 10:50:48 dedekind Exp $ + * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ * */ @@ -30,35 +30,33 @@ struct inode_operations jffs2_symlink_inode_operations = static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); - char *p = (char *)f->dents; - + char *p = (char *)f->target; + /* * We don't acquire the f->sem mutex here since the only data we - * use is f->dents which in case of the symlink inode points to the - * symlink's target path. + * use is f->target. * - * 1. If we are here the inode has already built and f->dents has + * 1. If we are here the inode has already built and f->target has * to point to the target path. - * 2. Nobody uses f->dents (if the inode is symlink's inode). The - * exception is inode freeing function which frees f->dents. But + * 2. Nobody uses f->target (if the inode is symlink's inode). The + * exception is inode freeing function which frees f->target. But * it can't be called while we are here and before VFS has - * stopped using our f->dents string which we provide by means of + * stopped using our f->target string which we provide by means of * nd_set_link() call. */ if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); p = ERR_PTR(-EIO); - } else { - D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); } + D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); nd_set_link(nd, p); /* - * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe - * since the only way that may cause f->dents to be changed is iput() operation. - * But VFS will not use f->dents after iput() has been called. + * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe + * since the only way that may cause f->target to be changed is iput() operation. + * But VFS will not use f->target after iput() has been called. */ return NULL; } diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index 6dbb1cce6646..a5db884ec607 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_i.h,v 1.17 2004/11/11 23:51:27 dwmw2 Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I @@ -32,6 +32,9 @@ struct jffs2_inode_info { /* Directory entries */ struct jffs2_full_dirent *dents; + /* The target path if this is the inode of a symlink */ + unsigned char *target; + /* Some stuff we just have to keep in-core at all times, for each inode. */ struct jffs2_inode_cache *inocache; -- cgit v1.2.3 From d3997abf699655d2ec012e944fb34668cc3ec6d7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 15:45:00 +0000 Subject: [ARM] Fix another use of // as a comment // disagrees with ld's script parsing ability. Don't use it. Signed-off-by: Russell King --- include/asm-arm/arch-iop3xx/iop331.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-iop3xx/iop331.h b/include/asm-arm/arch-iop3xx/iop331.h index 96adffd8bad2..fbf0cc11bdd9 100644 --- a/include/asm-arm/arch-iop3xx/iop331.h +++ b/include/asm-arm/arch-iop3xx/iop331.h @@ -42,7 +42,7 @@ /* this can be 128M if OMWTVR1 is set */ #define IOP331_PCI_MEM_WINDOW_SIZE 0x04000000 /* 64M outbound window */ -//#define IOP331_PCI_MEM_WINDOW_SIZE (~*IOP331_IALR1 + 1) +/* #define IOP331_PCI_MEM_WINDOW_SIZE (~*IOP331_IALR1 + 1) */ #define IOP331_PCI_LOWER_MEM_PA 0x80000000 #define IOP331_PCI_LOWER_MEM_BA (*IOP331_OMWTVR0) #define IOP331_PCI_UPPER_MEM_PA (IOP331_PCI_LOWER_MEM_PA + IOP331_PCI_MEM_WINDOW_SIZE - 1) -- cgit v1.2.3 From f302cd028c90ddbca20cb5388458ae0f0dd03d9b Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 24 Jul 2005 16:29:59 +0100 Subject: [JFFS2] Namespace clean up Rename functions to a name matching the functionality. Remove stall debug code Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 21 +-------------------- fs/jffs2/fs.c | 4 ++-- fs/jffs2/nodelist.h | 4 ++-- fs/jffs2/readinode.c | 6 +++--- include/linux/jffs2.h | 6 +++--- 5 files changed, 11 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 51ff099a6502..3c3c2940f272 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.5 2005/07/24 15:14:14 dedekind Exp $ + * $Id: debug.h,v 1.6 2005/07/24 15:18:26 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -15,25 +15,6 @@ #include -/* ------------------------------------------------ */ -/* TODO: remove */ -#undef CONFIG_JFFS2_FS_DEBUG -#define CONFIG_JFFS2_FS_DEBUG 0 -//#define JFFS2_DBG_PARANOIA_CHECKS -//#define JFFS2_DBG_DUMPS -#define JFFS2_DBG_READINODE_MESSAGES -//#define JFFS2_DBG_FRAGTREE_MESSAGES -//#define JFFS2_DBG_FRAGTREE2_MESSAGES -#undef KERN_DEBUG -#undef KERN_WARNING -#undef KERN_NOTICE -#undef KERN_ERR -#define KERN_DEBUG KERN_CRIT -#define KERN_WARNING KERN_CRIT -#define KERN_NOTICE KERN_CRIT -#define KERN_ERR KERN_CRIT -/* ------------------------------------------------ */ - #ifndef CONFIG_JFFS2_FS_DEBUG #define CONFIG_JFFS2_FS_DEBUG 1 #endif diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 34731614b57a..cc18b92234c4 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.60 2005/07/22 10:32:08 dedekind Exp $ + * $Id: fs.c,v 1.61 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -147,7 +147,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) old_metadata = f->metadata; if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) - jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size); + jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size); if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { jffs2_add_full_dnode_to_inode(c, f, new_metadata); diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index dde9b86e43b5..0058e395641b 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.133 2005/07/22 10:32:08 dedekind Exp $ + * $Id: nodelist.h,v 1.134 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -336,7 +336,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 02b02c1146bf..339ba46320fa 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.129 2005/07/22 10:32:08 dedekind Exp $ + * $Id: readinode.c,v 1.130 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -273,7 +273,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l return 0; } -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); @@ -534,7 +534,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ - jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize)); + jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); break; case S_IFLNK: diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 419fc953ac16..7bc51add62fa 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.34 2004/11/16 20:36:14 dwmw2 Exp $ + * $Id: jffs2.h,v 1.35 2005/07/24 15:15:51 dedekind Exp $ * */ @@ -101,7 +101,7 @@ struct jffs2_unknown_node struct jffs2_raw_dirent { jint16_t magic; - jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ jint32_t totlen; jint32_t hdr_crc; jint32_t pino; @@ -125,7 +125,7 @@ struct jffs2_raw_dirent struct jffs2_raw_inode { jint16_t magic; /* A constant magic number. */ - jint16_t nodetype; /* == JFFS_NODETYPE_INODE */ + jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ jint32_t totlen; /* Total length of this node (inc data, etc.) */ jint32_t hdr_crc; jint32_t ino; /* Inode number. */ -- cgit v1.2.3 From 2227c0ba4bc177a014d95b380b4d888454a127a9 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Tue, 26 Jul 2005 14:24:43 +0100 Subject: [jffs2] Remove compressor lzo and lzari Remove unused compressor code Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/compr.c | 14 +------------- fs/jffs2/compr.h | 10 +--------- include/linux/jffs2.h | 4 +--- 3 files changed, 3 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index af922a9618ac..c9e54b97dba8 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.42 2004/08/07 21:56:08 dwmw2 Exp $ + * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ * */ @@ -425,12 +425,6 @@ int jffs2_compressors_init(void) jffs2_rubinmips_init(); jffs2_dynrubin_init(); #endif -#ifdef CONFIG_JFFS2_LZARI - jffs2_lzari_init(); -#endif -#ifdef CONFIG_JFFS2_LZO - jffs2_lzo_init(); -#endif /* Setting default compression mode */ #ifdef CONFIG_JFFS2_CMODE_NONE jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; @@ -449,12 +443,6 @@ int jffs2_compressors_init(void) int jffs2_compressors_exit(void) { /* Unregistering compressors */ -#ifdef CONFIG_JFFS2_LZO - jffs2_lzo_exit(); -#endif -#ifdef CONFIG_JFFS2_LZARI - jffs2_lzari_exit(); -#endif #ifdef CONFIG_JFFS2_RUBIN jffs2_dynrubin_exit(); jffs2_rubinmips_exit(); diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 89ceeed201eb..9ec6e37d3833 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -7,7 +7,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr.h,v 1.6 2004/07/16 15:17:57 dwmw2 Exp $ + * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ * */ @@ -103,13 +103,5 @@ void jffs2_rtime_exit(void); int jffs2_zlib_init(void); void jffs2_zlib_exit(void); #endif -#ifdef CONFIG_JFFS2_LZARI -int jffs2_lzari_init(void); -void jffs2_lzari_exit(void); -#endif -#ifdef CONFIG_JFFS2_LZO -int jffs2_lzo_init(void); -void jffs2_lzo_exit(void); -#endif #endif /* __JFFS2_COMPR_H__ */ diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 7bc51add62fa..a66d0a8b70e4 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.35 2005/07/24 15:15:51 dedekind Exp $ + * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ * */ @@ -43,8 +43,6 @@ #define JFFS2_COMPR_COPY 0x04 #define JFFS2_COMPR_DYNRUBIN 0x05 #define JFFS2_COMPR_ZLIB 0x06 -#define JFFS2_COMPR_LZO 0x07 -#define JFFS2_COMPR_LZARI 0x08 /* Compatibility flags. */ #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ #define JFFS2_NODE_ACCURATE 0x2000 -- cgit v1.2.3 From 638d983840bb64e02c29bdd6160bb9963f4090f7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 6 Aug 2005 05:40:46 +0100 Subject: {MTD] add support for Intel's "Sibley" flash This updates the Primary Vendor-Specific Extended Query parsing to version 1.4 in order to get the information about the Configurable Programming Mode regions implemented in the Sibley flash, as well as selecting the appropriate write command code. This flash does not behave like traditional NOR flash when writing data. While mtdblock should just work, further changes are needed for JFFS2 use. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 88 +++++++++++++++++++++++++++---------- drivers/mtd/chips/gen_probe.c | 3 +- include/linux/mtd/cfi.h | 13 +++++- include/linux/mtd/mtd.h | 14 +++++- include/mtd/mtd-abi.h | 3 +- 5 files changed, 92 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 308855e80f66..10c50604bcd5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.181 2005/08/06 04:16:48 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.182 2005/08/06 04:40:41 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -105,6 +105,7 @@ static struct mtd_chip_driver cfi_intelext_chipdrv = { static void cfi_tell_features(struct cfi_pri_intelext *extp) { int i; + printk(" Extended Query version %c.%c\n", extp->MajorVersion, extp->MinorVersion); printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); @@ -116,7 +117,8 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported"); - for (i=10; i<32; i++) { + printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported"); + for (i=11; i<32; i++) { if (extp->FeatureSupport & (1<BlkStatusRegMask); printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); - printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); - for (i=2; i<16; i++) { + printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); + for (i=2; i<3; i++) { if (extp->BlkStatusRegMask & (1<BlkStatusRegMask&16?"yes":"no"); + printk(" - EFA Lock-Down Bit: %s\n", extp->BlkStatusRegMask&32?"yes":"no"); + for (i=6; i<16; i++) { + if (extp->BlkStatusRegMask & (1<VccOptimal >> 4, extp->VccOptimal & 0xf); if (extp->VppOptimal) @@ -253,7 +261,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) return NULL; if (extp->MajorVersion != '1' || - (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { + (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { printk(KERN_ERR " Unknown Intel/Sharp Extended Query " "version %c.%c.\n", extp->MajorVersion, extp->MinorVersion); @@ -266,7 +274,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); - if (extp->MajorVersion == '1' && extp->MinorVersion == '3') { + if (extp->MajorVersion == '1' && extp->MinorVersion >= '3') { unsigned int extra_size = 0; int nb_parts, i; @@ -275,7 +283,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - extra_size += 6; + extra_size += (extp->MinorVersion < '4') ? 6 : 5; /* Number of hardware-partitions */ extra_size += 1; @@ -283,6 +291,10 @@ read_pri_intelext(struct map_info *map, __u16 adr) goto need_more; nb_parts = extp->extra[extra_size - 1]; + /* skip the sizeof(partregion) field in CFI 1.4 */ + if (extp->MinorVersion >= '4') + extra_size += 2; + for (i = 0; i < nb_parts; i++) { struct cfi_intelext_regioninfo *rinfo; rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; @@ -294,6 +306,9 @@ read_pri_intelext(struct map_info *map, __u16 adr) * sizeof(struct cfi_intelext_blockinfo); } + if (extp->MinorVersion >= '4') + extra_size += sizeof(struct cfi_intelext_programming_regioninfo); + if (extp_size < sizeof(*extp) + extra_size) { need_more: extp_size = sizeof(*extp) + extra_size; @@ -490,7 +505,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, * arrangement at this point. This can be rearranged in the future * if someone feels motivated enough. --nico */ - if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3' + if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3' && extp->FeatureSupport & (1 << 9)) { struct cfi_private *newcfi; struct flchip *chip; @@ -502,12 +517,16 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - offs += 6; + offs += (extp->MinorVersion < '4') ? 6 : 5; /* Number of partition regions */ numregions = extp->extra[offs]; offs += 1; + /* skip the sizeof(partregion) field in CFI 1.4 */ + if (extp->MinorVersion >= '4') + offs += 2; + /* Number of hardware partitions */ numparts = 0; for (i = 0; i < numregions; i++) { @@ -519,6 +538,20 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_blockinfo); } + /* Programming Region info */ + if (extp->MinorVersion >= '4') { + struct cfi_intelext_programming_regioninfo *prinfo; + prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs]; + MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift; + MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid; + MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid; + mtd->flags |= MTD_PROGRAM_REGIONS; + printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n", + map->name, MTD_PROGREGION_SIZE(mtd), + MTD_PROGREGION_CTRLMODE_VALID(mtd), + MTD_PROGREGION_CTRLMODE_INVALID(mtd)); + } + /* * All functions below currently rely on all chips having * the same geometry so we'll just assume that all hardware @@ -1222,12 +1255,17 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, adr += chip->start; - /* Let's determine this according to the interleave only once */ + /* Let's determine those according to the interleave only once */ status_OK = CMD(0x80); switch (mode) { - case FL_WRITING: write_cmd = CMD(0x40); break; - case FL_OTP_WRITE: write_cmd = CMD(0xc0); break; - default: return -EINVAL; + case FL_WRITING: + write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); + break; + case FL_OTP_WRITE: + write_cmd = CMD(0xc0); + break; + default: + return -EINVAL; } spin_lock(chip->mutex); @@ -1410,16 +1448,17 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK; + map_word status, status_OK, write_cmd; unsigned long cmd_adr, timeo; int wbufsize, z, ret=0, bytes, words; wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; cmd_adr = adr & ~(wbufsize-1); - + /* Let's determine this according to the interleave only once */ status_OK = CMD(0x80); + write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); spin_lock(chip->mutex); ret = get_chip(map, chip, cmd_adr, FL_WRITING); @@ -1451,7 +1490,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, z = 0; for (;;) { - map_write(map, CMD(0xe8), cmd_adr); + map_write(map, write_cmd, cmd_adr); status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) @@ -2380,20 +2419,23 @@ static void cfi_intelext_destroy(struct mtd_info *mtd) kfree(mtd->eraseregions); } -static char im_name_1[]="cfi_cmdset_0001"; -static char im_name_3[]="cfi_cmdset_0003"; +static char im_name_0001[] = "cfi_cmdset_0001"; +static char im_name_0003[] = "cfi_cmdset_0003"; +static char im_name_0200[] = "cfi_cmdset_0200"; static int __init cfi_intelext_init(void) { - inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001); - inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001); return 0; } static void __exit cfi_intelext_exit(void) { - inter_module_unregister(im_name_1); - inter_module_unregister(im_name_3); + inter_module_unregister(im_name_0001); + inter_module_unregister(im_name_0003); + inter_module_unregister(im_name_0200); } module_init(cfi_intelext_init); diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index dc065b22f79e..28807eb9fc86 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -2,7 +2,7 @@ * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.22 2005/01/24 23:49:50 rmk Exp $ + * $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $ */ #include @@ -235,6 +235,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) #ifdef CONFIG_MTD_CFI_INTELEXT case 0x0001: case 0x0003: + case 0x0200: return cfi_cmdset_0001(map, primary); #endif #ifdef CONFIG_MTD_CFI_AMDSTD diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index e6b6a1c66bd5..360cf626c288 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $ + * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $ */ #ifndef __MTD_CFI_H__ @@ -173,6 +173,15 @@ struct cfi_intelext_regioninfo { struct cfi_intelext_blockinfo BlockTypes[1]; } __attribute__((packed)); +struct cfi_intelext_programming_regioninfo { + uint8_t ProgRegShift; + uint8_t Reserved1; + uint8_t ControlValid; + uint8_t Reserved2; + uint8_t ControlInvalid; + uint8_t Reserved3; +} __attribute__((packed)); + /* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ struct cfi_pri_amdstd { @@ -316,7 +325,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf #define CMD(x) cfi_build_cmd((x), map, cfi) -static inline unsigned char cfi_merge_status(map_word val, struct map_info *map, +static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, struct cfi_private *cfi) { int wordwidth, words_per_bus, chip_mode, chips_per_word; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index c50c3f3927d9..ab5804183916 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ /* - * $Id: mtd.h,v 1.59 2005/04/11 10:19:02 gleixner Exp $ + * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $ * * Copyright (C) 1999-2003 David Woodhouse et al. * @@ -72,7 +72,17 @@ struct mtd_info { u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) u_int32_t ecctype; u_int32_t eccsize; - + + /* + * Reuse some of the above unused fields in the case of NOR flash + * with configurable programming regions to avoid modifying the + * user visible structure layout/size. Only valid when the + * MTD_PROGRAM_REGIONS flag is set. + * (Maybe we should have an union for those?) + */ +#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock +#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize +#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype // Kernel-only stuff starts here. char *name; diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 428d9122940b..16e74cafd0b4 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -1,5 +1,5 @@ /* - * $Id: mtd-abi.h,v 1.11 2005/05/19 16:08:58 gleixner Exp $ + * $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $ * * Portions of MTD ABI definition which are shared by kernel and user space */ @@ -42,6 +42,7 @@ struct mtd_oob_buf { #define MTD_OOB 64 // Out-of-band data (NAND flash) #define MTD_ECC 128 // Device capable of automatic ECC #define MTD_NO_VIRTBLOCKS 256 // Virtual blocks not allowed +#define MTD_PROGRAM_REGIONS 512 // Configurable Programming Regions // Some common devices / combinations of capabilities #define MTD_CAP_ROM 0 -- cgit v1.2.3 From 4fe15ba08fdb280536bd7019e8505969c4ac6852 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 19:47:04 +0000 Subject: [ARM] Fix second missing declaration of cache_is_vivt() Signed-off-by: Russell King --- arch/arm/kernel/ecard.c | 1 - include/asm-arm/mmu_context.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index c445b0a848b2..dceb826bd216 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h index 57b8def83d41..3d4b810d8c38 100644 --- a/include/asm-arm/mmu_context.h +++ b/include/asm-arm/mmu_context.h @@ -13,6 +13,7 @@ #ifndef __ASM_ARM_MMU_CONTEXT_H #define __ASM_ARM_MMU_CONTEXT_H +#include #include #if __LINUX_ARM_ARCH__ >= 6 -- cgit v1.2.3 From cd5f6346bc28a41375412b49b290d22ee4e4bbe8 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Mon, 11 Jul 2005 11:41:53 +0100 Subject: [MTD] Add initial support for OneNAND flash chips OneNAND is a new flash technology from Samsung with integrated SRAM buffers and logic interface. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/Kconfig | 10 +- drivers/mtd/Makefile | 4 +- drivers/mtd/onenand/Kconfig | 32 + drivers/mtd/onenand/Makefile | 9 + drivers/mtd/onenand/omap-onenand.c | 178 +++++ drivers/mtd/onenand/onenand_base.c | 1462 ++++++++++++++++++++++++++++++++++++ include/linux/mtd/onenand.h | 134 ++++ include/linux/mtd/onenand_regs.h | 167 ++++ 8 files changed, 1990 insertions(+), 6 deletions(-) create mode 100644 drivers/mtd/onenand/Kconfig create mode 100644 drivers/mtd/onenand/Makefile create mode 100644 drivers/mtd/onenand/omap-onenand.c create mode 100644 drivers/mtd/onenand/onenand_base.c create mode 100644 include/linux/mtd/onenand.h create mode 100644 include/linux/mtd/onenand_regs.h (limited to 'include') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 843a1cbe0866..3dbfbafb3481 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1,4 +1,4 @@ -# $Id: Kconfig,v 1.9 2005/06/16 08:49:29 sean Exp $ +# $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $ menu "Memory Technology Devices (MTD)" @@ -259,9 +259,9 @@ config RFD_FTL ---help--- This provides support for the flash translation layer known as the Resident Flash Disk (RFD), as used by the Embedded BIOS - of General Software. - See http://www.gensw.com/pages/prod/bios/rfd.htm for further - information. + of General Software. There is a blurb at: + + http://www.gensw.com/pages/prod/bios/rfd.htm source "drivers/mtd/chips/Kconfig" @@ -271,5 +271,7 @@ source "drivers/mtd/devices/Kconfig" source "drivers/mtd/nand/Kconfig" +source "drivers/mtd/onenand/Kconfig" + endmenu diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index cb16b7d478ce..fc9374407c2b 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -1,7 +1,7 @@ # # Makefile for the memory technology device drivers. # -# $Id: Makefile.common,v 1.6 2005/06/16 08:49:29 sean Exp $ +# $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $ # Core functionality. mtd-y := mtdcore.o @@ -25,4 +25,4 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o nftl-objs := nftlcore.o nftlmount.o inftl-objs := inftlcore.o inftlmount.o -obj-y += chips/ maps/ devices/ nand/ +obj-y += chips/ maps/ devices/ nand/ onenand/ diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig new file mode 100644 index 000000000000..7d76ede984d8 --- /dev/null +++ b/drivers/mtd/onenand/Kconfig @@ -0,0 +1,32 @@ +# +# linux/drivers/mtd/onenand/Kconfig +# + +menu "OneNAND Flash Device Drivers (EXPERIMENTAL)" + depends on MTD != n && EXPERIMENTAL + +config MTD_ONENAND + tristate "OneNAND Device Support" + depends on MTD + help + This enables support for accessing all type of OneNAND flash + devices. For further information see + . + +config MTD_ONENAND_VERIFY_WRITE + bool "Verify OneNAND page writes" + depends on MTD_ONENAND + help + This adds an extra check when data is written to the flash. The + OneNAND flash device internally checks only bits transitioning + from 1 to 0. There is a rare possibility that even though the + device thinks the write was successful, a bit could have been + flipped accidentaly due to device wear or something else. + +config MTD_ONENAND_OMAP + tristate "OneNAND Flash device on OMAP board" + depends on ARCH_OMAP && MTD_ONENAND + help + Support for OneNAND flash on TI OMAP board. + +endmenu diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile new file mode 100644 index 000000000000..f4e75864d8b5 --- /dev/null +++ b/drivers/mtd/onenand/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the OneNAND MTD +# + +# Core functionality. +obj-$(CONFIG_MTD_ONENAND) += onenand_base.o + +# Board specific. +obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c new file mode 100644 index 000000000000..56e1aec6b835 --- /dev/null +++ b/drivers/mtd/onenand/omap-onenand.c @@ -0,0 +1,178 @@ +/* + * linux/drivers/mtd/onenand/omap-onenand.c + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * Derived from linux/drivers/mtd/nand/omap-nand-flash.c + * + * 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. + * + * Overview: + * This is a device driver for the OneNAND flash device for TI OMAP boards. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS +#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS +/* + * MTD structure for OMAP board + */ +static struct mtd_info *omap_onenand_mtd = NULL; + +/* + * Define partitions for flash devices + */ + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition static_partition[] = { + { + .name = "X-Loader + U-Boot", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot Environment", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 2 * SZ_1M + }, + { + .name = "filesystem0", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M, + }, + { + .name = "filesystem1", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +const char *part_probes[] = { "cmdlinepart", NULL, }; + +#endif + +/* Scan to find existance of the device at base. + This also allocates oob and data internal buffers */ +static char onenand_name[] = "onenand"; + +/* + * Main initialization routine + */ +static int __init omap_onenand_init (void) +{ + struct onenand_chip *this; + struct mtd_partition *dynamic_partition = 0; + int err = 0; + + /* Allocate memory for MTD device structure and private data */ + omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), + GFP_KERNEL); + if (!omap_onenand_mtd) { + printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + /* Get pointer to private data */ + this = (struct onenand_chip *) (&omap_onenand_mtd[1]); + + /* Initialize structures */ + memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); + + /* Link the private data with the MTD structure */ + omap_onenand_mtd->priv = this; + + /* try the first address */ + this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); + omap_onenand_mtd->name = onenand_name; + if (onenand_scan(omap_onenand_mtd, 1)){ + /* try the second address */ + iounmap(this->base); + this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); + if (onenand_scan(omap_onenand_mtd, 1)) { + iounmap(this->base); + err = -ENXIO; + goto out_mtd; + } + } + + /* Register the partitions */ + switch (omap_onenand_mtd->size) { + case SZ_128M: + case SZ_64M: + case SZ_32M: +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(omap_onenand_mtd, part_probes, + &dynamic_partition, 0); + if (err > 0) + err = add_mtd_partitions(omap_onenand_mtd, + dynamic_partition, err); + else if (1) + err = add_mtd_partitions(omap_onenand_mtd, + static_partition, + ARRAY_SIZE(static_partition)); + else +#endif + err = add_mtd_device(omap_onenand_mtd); + if (err) + goto out_buf; + break; + + default: + printk(KERN_WARNING "Unsupported OneNAND device\n"); + err = -ENXIO; + goto out_buf; + } + + return 0; + +out_buf: + onenand_release(omap_onenand_mtd); + iounmap(this->base); +out_mtd: + kfree(omap_onenand_mtd); +out: + return err; +} + +/* + * Clean up routine + */ +static void __exit omap_onenand_cleanup (void) +{ + struct onenand_chip *this = omap_onenand_mtd->priv; + + /* onenand_release frees MTD partitions, MTD structure + and onenand internal buffers */ + onenand_release(omap_onenand_mtd); + iounmap(this->base); + kfree(omap_onenand_mtd); +} + +module_init(omap_onenand_init); +module_exit(omap_onenand_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards"); diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c new file mode 100644 index 000000000000..bcce22ae3cb1 --- /dev/null +++ b/drivers/mtd/onenand/onenand_base.c @@ -0,0 +1,1462 @@ +/* + * linux/drivers/mtd/onenand/onenand_base.c + * + * Copyright (C) 2005 Samsung Electronics + * Kyungmin Park + * + * 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 + +/** + * onenand_oob_64 - oob info for large (2KB) page + */ +static struct nand_oobinfo onenand_oob_64 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 20, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + 40, 41, 42, 43, 44, + 56, 57, 58, 59, 60, + }, + .oobfree = { + {2, 3}, {14, 2}, {18, 3}, {30, 2}, + {24, 3}, {46, 2}, {40, 3}, {62, 2} } +}; + +/** + * onenand_oob_32 - oob info for middle (1KB) page + */ +static struct nand_oobinfo onenand_oob_32 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 10, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + }, + .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } +}; + +static const unsigned char ffchars[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ +}; + +/** + * onenand_readw - [OneNAND Interface] Read OneNAND register + * @param addr address to read + * + * Read OneNAND register + */ +static unsigned short onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +/** + * onenand_writew - [OneNAND Interface] Write OneNAND register with value + * @param value value to write + * @param addr address to write + * + * Write OneNAND register with value + */ +static void onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +/** + * onenand_block_address - [DEFAULT] Get block address + * @param device the device id + * @param block the block + * @return translated block address if DDP, otherwise same + * + * Setup Start Address 1 Register (F100h) + */ +static int onenand_block_address(int device, int block) +{ + if (device & ONENAND_DEVICE_IS_DDP) { + /* Device Flash Core select, NAND Flash Block Address */ + int dfs = 0, density, mask; + + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + mask = (1 << (density + 6)); + + if (block & mask) + dfs = 1; + + return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); + } + + return block; +} + +/** + * onenand_bufferram_address - [DEFAULT] Get bufferram address + * @param device the device id + * @param block the block + * @return set DBS value if DDP, otherwise 0 + * + * Setup Start Address 2 Register (F101h) for DDP + */ +static int onenand_bufferram_address(int device, int block) +{ + if (device & ONENAND_DEVICE_IS_DDP) { + /* Device BufferRAM Select */ + int dbs = 0, density, mask; + + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + mask = (1 << (density + 6)); + + if (block & mask) + dbs = 1; + + return (dbs << ONENAND_DDP_SHIFT); + } + + return 0; +} + +/** + * onenand_page_address - [DEFAULT] Get page address + * @param page the page address + * @param sector the sector address + * @return combined page and sector address + * + * Setup Start Address 8 Register (F107h) + */ +static int onenand_page_address(int page, int sector) +{ + /* Flash Page Address, Flash Sector Address */ + int fpa, fsa; + + fpa = page & ONENAND_FPA_MASK; + fsa = sector & ONENAND_FSA_MASK; + + return ((fpa << ONENAND_FPA_SHIFT) | fsa); +} + +/** + * onenand_buffer_address - [DEFAULT] Get buffer address + * @param dataram1 DataRAM index + * @param sectors the sector address + * @param count the number of sectors + * @return the start buffer value + * + * Setup Start Buffer Register (F200h) + */ +static int onenand_buffer_address(int dataram1, int sectors, int count) +{ + int bsa, bsc; + + /* BufferRAM Sector Address */ + bsa = sectors & ONENAND_BSA_MASK; + + if (dataram1) + bsa |= ONENAND_BSA_DATARAM1; /* DataRAM1 */ + else + bsa |= ONENAND_BSA_DATARAM0; /* DataRAM0 */ + + /* BufferRAM Sector Count */ + bsc = count & ONENAND_BSC_MASK; + + return ((bsa << ONENAND_BSA_SHIFT) | bsc); +} + +/** + * onenand_command - [DEFAULT] Send command to OneNAND device + * @param mtd MTD device structure + * @param cmd the command to be sent + * @param addr offset to read from or write to + * @param len number of bytes to read or write + * + * Send command to OneNAND device. This function is used for middle/large page + * devices (1KB/2KB Bytes per page) + */ +static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) +{ + struct onenand_chip *this = mtd->priv; + int value, readcmd = 0; + int block, page; + /* Now we use page size operation */ + int sectors = 4, count = 4; + + /* Address translation */ + switch (cmd) { + case ONENAND_CMD_UNLOCK: + case ONENAND_CMD_LOCK: + case ONENAND_CMD_LOCK_TIGHT: + block = -1; + page = -1; + break; + + case ONENAND_CMD_ERASE: + case ONENAND_CMD_BUFFERRAM: + block = (int) (addr >> this->erase_shift); + page = -1; + break; + + default: + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + break; + } + + /* NOTE: The setting order of the registers is very important! */ + if (cmd == ONENAND_CMD_BUFFERRAM) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + + /* Switch to the next data buffer */ + ONENAND_SET_NEXT_BUFFERRAM(this); + + return 0; + } + + if (block != -1) { + /* Write 'DFS, FBA' of Flash */ + value = onenand_block_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + } + + if (page != -1) { + int dataram; + + switch (cmd) { + case ONENAND_CMD_READ: + case ONENAND_CMD_READOOB: + dataram = ONENAND_SET_NEXT_BUFFERRAM(this); + readcmd = 1; + break; + + default: + dataram = ONENAND_CURRENT_BUFFERRAM(this); + break; + } + + /* Write 'FPA, FSA' of Flash */ + value = onenand_page_address(page, sectors); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS8); + + /* Write 'BSA, BSC' of DataRAM */ + value = onenand_buffer_address(dataram, sectors, count); + this->write_word(value, this->base + ONENAND_REG_START_BUFFER); + + if (readcmd) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + } + } + + /* Interrupt clear */ + this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT); + + /* Write command */ + this->write_word(cmd, this->base + ONENAND_REG_COMMAND); + + return 0; +} + +/** + * onenand_wait - [DEFAULT] wait until the command is done + * @param mtd MTD device structure + * @param state state to select the max. timeout value + * + * Wait for command done. This applies to all OneNAND command + * Read can take up to 30us, erase up to 2ms and program up to 350us + * according to general OneNAND specs + */ +static int onenand_wait(struct mtd_info *mtd, int state) +{ + struct onenand_chip * this = mtd->priv; + unsigned long timeout; + unsigned int flags = ONENAND_INT_MASTER; + unsigned int interrupt = 0; + unsigned int ctrl, ecc; + + /* The 20 msec is enough */ + timeout = jiffies + msecs_to_jiffies(20); + while (time_before(jiffies, timeout)) { + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); + + if (interrupt & flags) + break; + + if (state != FL_READING) + cond_resched(); + } + /* To get correct interrupt status in timeout case */ + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); + + ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); + + if (ctrl & ONENAND_CTRL_ERROR) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); + return -EIO; + } + + if (ctrl & ONENAND_CTRL_LOCK) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); + return -EIO; + } + + if (interrupt & ONENAND_INT_READ) { + ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); + if (ecc & ONENAND_ECC_2BIT_ALL) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); + return -EBADMSG; + } + } + + return 0; +} + +/** + * onenand_bufferram_offset - [DEFAULT] BufferRAM offset + * @param mtd MTD data structure + * @param area BufferRAM area + * @return offset given area + * + * Return BufferRAM offset given area + */ +static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) +{ + struct onenand_chip *this = mtd->priv; + + if (ONENAND_CURRENT_BUFFERRAM(this)) { + if (area == ONENAND_DATARAM) + return mtd->oobblock; + if (area == ONENAND_SPARERAM) + return mtd->oobsize; + } + + return 0; +} + +/** + * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Read the BufferRAM area + */ +static int onenand_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + memcpy(buffer, bufferram + offset, count); + + return 0; +} + +/** + * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Write the BufferRAM area + */ +static int onenand_write_bufferram(struct mtd_info *mtd, int area, + const unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + memcpy(bufferram + offset, buffer, count); + + return 0; +} + +/** + * onenand_check_bufferram - [GENERIC] Check BufferRAM information + * @param mtd MTD data structure + * @param addr address to check + * @return 1 if there are valid data, otherwise 0 + * + * Check bufferram if there is data we required + */ +static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) +{ + struct onenand_chip *this = mtd->priv; + int block, page; + int i; + + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + + i = ONENAND_CURRENT_BUFFERRAM(this); + + /* Is there valid data? */ + if (this->bufferram[i].block == block && + this->bufferram[i].page == page && + this->bufferram[i].valid) + return 1; + + return 0; +} + +/** + * onenand_update_bufferram - [GENERIC] Update BufferRAM information + * @param mtd MTD data structure + * @param addr address to update + * @param valid valid flag + * + * Update BufferRAM information + */ +static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, + int valid) +{ + struct onenand_chip *this = mtd->priv; + int block, page; + int i; + + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + + /* Invalidate BufferRAM */ + for (i = 0; i < MAX_BUFFERRAM; i++) { + if (this->bufferram[i].block == block && + this->bufferram[i].page == page) + this->bufferram[i].valid = 0; + } + + /* Update BufferRAM */ + i = ONENAND_CURRENT_BUFFERRAM(this); + this->bufferram[i].block = block; + this->bufferram[i].page = page; + this->bufferram[i].valid = valid; + + return 0; +} + +/** + * onenand_get_device - [GENERIC] Get chip for selected access + * @param mtd MTD device structure + * @param new_state the state which is requested + * + * Get the device and lock it for exclusive access + */ +static void onenand_get_device(struct mtd_info *mtd, int new_state) +{ + struct onenand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + /* + * Grab the lock and see if the device is available + */ + while (1) { + spin_lock(&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock(&this->chip_lock); + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&this->wq, &wait); + spin_unlock(&this->chip_lock); + schedule(); + remove_wait_queue(&this->wq, &wait); + } +} + +/** + * onenand_release_device - [GENERIC] release chip + * @param mtd MTD device structure + * + * Deselect, release chip lock and wake up anyone waiting on the device + */ +static void onenand_release_device(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + + /* Release the chip */ + spin_lock(&this->chip_lock); + this->state = FL_READY; + wake_up(&this->wq); + spin_unlock(&this->chip_lock); +} + +/** + * onenand_read_ecc - [MTD Interface] Read data with ECC + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * @param oob_buf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND read with ECC + */ +static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, + u_char *oob_buf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + int read = 0, column; + int thislen; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n"); + *retlen = 0; + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_READING); + + /* TODO handling oob */ + + while (read < len) { + thislen = min_t(int, mtd->oobblock, len - read); + + column = from & (mtd->oobblock - 1); + if (column + thislen > mtd->oobblock) + thislen = mtd->oobblock - column; + + if (!onenand_check_bufferram(mtd, from)) { + this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock); + + ret = this->wait(mtd, FL_READING); + /* First copy data and check return value for ECC handling */ + onenand_update_bufferram(mtd, from, 1); + } + + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); + + read += thislen; + + if (read == len) + break; + + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret); + goto out; + } + + from += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + /* + * Return success, if no ECC failures, else -EBADMSG + * fs driver will take care of that, because + * retlen == desired len and result == -EBADMSG + */ + *retlen = read; + return ret; +} + +/** + * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * + * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL +*/ +static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); +} + +/** + * onenand_read_oob - [MTD Interface] OneNAND read out-of-band + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * + * OneNAND read out-of-band data from the spare area + */ +static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int read = 0, thislen, column; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow reads past end of device */ + if (unlikely((from + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempt read beyond end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_READING); + + column = from & (mtd->oobsize - 1); + + while (read < len) { + thislen = mtd->oobsize - column; + thislen = min_t(int, thislen, len); + + this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); + + onenand_update_bufferram(mtd, from, 0); + + ret = this->wait(mtd, FL_READING); + /* First copy data and check return value for ECC handling */ + + this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + + read += thislen; + + if (read == len) + break; + + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret); + goto out; + } + + buf += thislen; + + /* Read more? */ + if (read < len) { + /* Page size */ + from += mtd->oobblock; + column = 0; + } + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = read; + return ret; +} + +#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE +/** + * onenand_verify_page - [GENERIC] verify the chip contents after a write + * @param mtd MTD device structure + * @param buf the databuffer to verify + * @param block block address + * @param page page address + * + * Check DataRAM area directly + */ +static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, + loff_t addr, int block, int page) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *dataram0, *dataram1; + int ret = 0; + + this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock); + + ret = this->wait(mtd, FL_READING); + if (ret) + return ret; + + onenand_update_bufferram(mtd, addr, 1); + + /* Check, if the two dataram areas are same */ + dataram0 = this->base + ONENAND_DATARAM; + dataram1 = dataram0 + mtd->oobblock; + + if (memcmp(dataram0, dataram1, mtd->oobblock)) + return -EBADMSG; + + return 0; +} +#else +#define onenand_verify_page(...) (0) +#endif + +#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0) + +/** + * onenand_write_ecc - [MTD Interface] OneNAND write with ECC + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * @param eccbuf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND write with ECC + */ +static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, + u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + int written = 0; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow writes past end of device */ + if (unlikely((to + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n"); + return -EINVAL; + } + + /* Reject writes, which are not page aligned */ + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* Loop until all data write */ + while (written < len) { + int thislen = min_t(int, mtd->oobblock, len - written); + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + + this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + + onenand_update_bufferram(mtd, to, 1); + + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret); + goto out; + } + + written += thislen; + + /* Only check verify write turn on */ + ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); + goto out; + } + + if (written == len) + break; + + to += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return ret; +} + +/** + * onenand_write - [MTD Interface] compability function for onenand_write_ecc + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * + * This function simply calls onenand_write_ecc + * with oob buffer and oobsel = NULL + */ +static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL); +} + +/** + * onenand_write_oob - [MTD Interface] OneNAND write out-of-band + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * + * OneNAND write out-of-band + */ +static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int column, status; + int written = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow writes past end of device */ + if (unlikely((to + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempt write to past end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* Loop until all data write */ + while (written < len) { + int thislen = min_t(int, mtd->oobsize, len - written); + + column = to & (mtd->oobsize - 1); + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize); + + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + + this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); + + onenand_update_bufferram(mtd, to, 0); + + status = this->wait(mtd, FL_WRITING); + if (status) + goto out; + + written += thislen; + + if (written == len) + break; + + to += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return 0; +} + +/** + * onenand_writev_ecc - [MTD Interface] write with iovec with ecc + * @param mtd MTD device structure + * @param vecs the iovectors to write + * @param count number of vectors + * @param to offset to write to + * @param retlen pointer to variable to store the number of written bytes + * @param eccbuf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND write with iovec with ecc + */ +static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen, + u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + unsigned char buffer[mtd->oobblock], *pbuf; + size_t total_len, len; + int i, written = 0; + int ret = 0; + + /* Preset written len for early exit */ + *retlen = 0; + + /* Calculate total length of data */ + total_len = 0; + for (i = 0; i < count; i++) + total_len += vecs[i].iov_len; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); + + /* Do not allow write past end of the device */ + if (unlikely((to + total_len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n"); + return -EINVAL; + } + + /* Reject writes, which are not page aligned */ + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* TODO handling oob */ + + /* Loop until all keve's data has been written */ + len = 0; + while (count) { + pbuf = buffer; + /* + * If the given tuple is >= pagesize then + * write it out from the iov + */ + if ((vecs->iov_len - len) >= mtd->oobblock) { + pbuf = vecs->iov_base + len; + + len += mtd->oobblock; + + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } else { + int cnt = 0, thislen; + while (cnt < mtd->oobblock) { + thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len); + memcpy(buffer + cnt, vecs->iov_base + len, thislen); + cnt += thislen; + len += thislen; + + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } + } + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + + this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock); + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + + onenand_update_bufferram(mtd, to, 1); + + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret); + goto out; + } + + + /* Only check verify write turn on */ + ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); + goto out; + } + + written += mtd->oobblock; + + to += mtd->oobblock; + } + +out: + /* Deselect and wakt up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return 0; +} + +/** + * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc + * @param mtd MTD device structure + * @param vecs the iovectors to write + * @param count number of vectors + * @param to offset to write to + * @param retlen pointer to variable to store the number of written bytes + * + * OneNAND write with kvec. This just calls the ecc function + */ +static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen) +{ + return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); +} + +/** + * onenand_erase - [MTD Interface] erase block(s) + * @param mtd MTD device structure + * @param instr erase instruction + * + * Erase one ore more blocks + */ +static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct onenand_chip *this = mtd->priv; + unsigned int block_size; + loff_t addr; + int len; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); + + block_size = (1 << this->erase_shift); + + /* Start address must align on block boundary */ + if (unlikely(instr->addr & (block_size - 1))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n"); + return -EINVAL; + } + + /* Length must align on block boundary */ + if (unlikely(instr->len & (block_size - 1))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if (unlikely((instr->len + instr->addr) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n"); + return -EINVAL; + } + + instr->fail_addr = 0xffffffff; + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_ERASING); + + /* Loop throught the pages */ + len = instr->len; + addr = instr->addr; + + instr->state = MTD_ERASING; + + while (len) { + + /* TODO Check badblock */ + + this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); + + ret = this->wait(mtd, FL_ERASING); + /* Check, if it is write protected */ + if (ret) { + if (ret == -EPERM) + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n"); + else + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); + instr->state = MTD_ERASE_FAILED; + instr->fail_addr = addr; + goto erase_exit; + } + + len -= block_size; + addr += block_size; + } + + instr->state = MTD_ERASE_DONE; + +erase_exit: + + ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; + /* Do call back function */ + if (!ret) + mtd_erase_callback(instr); + + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + return ret; +} + +/** + * onenand_sync - [MTD Interface] sync + * @param mtd MTD device structure + * + * Sync is actually a wait for chip ready function + */ +static void onenand_sync(struct mtd_info *mtd) +{ + DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n"); + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_SYNCING); + + /* Release it and go back */ + onenand_release_device(mtd); +} + +/** + * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + */ +static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + /* + * TODO + * 1. Bad block table (BBT) + * -> using NAND BBT to support JFFS2 + * 2. Bad block management (BBM) + * -> bad block replace scheme + * + * Currently we do nothing + */ + return 0; +} + +/** + * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + */ +static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + /* see above */ + return 0; +} + +/** + * onenand_unlock - [MTD Interface] Unlock block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to unlock + * + * Unlock one or more blocks + */ +static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct onenand_chip *this = mtd->priv; + int start, end, block, value, status; + + start = ofs >> this->erase_shift; + end = len >> this->erase_shift; + + /* Continuous lock scheme */ + if (this->options & ONENAND_CONT_LOCK) { + /* Set start block address */ + this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Set end block address */ + this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_UNLOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + if (!(status & ONENAND_WP_US)) + printk(KERN_ERR "wp status = 0x%x\n", status); + + return 0; + } + + /* Block lock scheme */ + for (block = start; block < end; block++) { + /* Set start block address */ + this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_UNLOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + /* Set block address for read block status */ + value = onenand_block_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + if (!(status & ONENAND_WP_US)) + printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); + } + + return 0; +} + +/** + * onenand_print_device_info - Print device ID + * @param device device ID + * + * Print device ID + */ +static void onenand_print_device_info(int device) +{ + int vcc, demuxed, ddp, density; + + vcc = device & ONENAND_DEVICE_VCC_MASK; + demuxed = device & ONENAND_DEVICE_IS_DEMUX; + ddp = device & ONENAND_DEVICE_IS_DDP; + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", + demuxed ? "" : "Muxed ", + ddp ? "(DDP)" : "", + (16 << density), + vcc ? "2.65/3.3" : "1.8", + device); +} + +static const struct onenand_manufacturers onenand_manuf_ids[] = { + {ONENAND_MFR_SAMSUNG, "Samsung"}, + {ONENAND_MFR_UNKNOWN, "Unknown"} +}; + +/** + * onenand_check_maf - Check manufacturer ID + * @param manuf manufacturer ID + * + * Check manufacturer ID + */ +static int onenand_check_maf(int manuf) +{ + int i; + + for (i = 0; onenand_manuf_ids[i].id; i++) { + if (manuf == onenand_manuf_ids[i].id) + break; + } + + printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", + onenand_manuf_ids[i].name); + + return (i != ONENAND_MFR_UNKNOWN); +} + +/** + * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * @param mtd MTD device structure + * + * OneNAND detection method: + * Compare the the values from command with ones from register + */ +static int onenand_probe(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + int bram_maf_id, bram_dev_id, maf_id, dev_id; + int version_id; + int density; + + /* Send the command for reading device ID from BootRAM */ + this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM); + + /* Read manufacturer and device IDs from BootRAM */ + bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0); + bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2); + + /* Check manufacturer ID */ + if (onenand_check_maf(bram_maf_id)) + return -ENXIO; + + /* Reset OneNAND to read default register values */ + this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); + + /* Read manufacturer and device IDs from Register */ + maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); + dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); + + /* Check OneNAND device */ + if (maf_id != bram_maf_id || dev_id != bram_dev_id) + return -ENXIO; + + /* Flash device information */ + onenand_print_device_info(dev_id); + this->device_id = dev_id; + + density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; + this->chipsize = (16 << density) << 20; + + /* OneNAND page size & block size */ + /* The data buffer size is equal to page size */ + mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); + mtd->oobsize = mtd->oobblock >> 5; + /* Pagers per block is always 64 in OneNAND */ + mtd->erasesize = mtd->oobblock << 6; + + this->erase_shift = ffs(mtd->erasesize) - 1; + this->page_shift = ffs(mtd->oobblock) - 1; + this->ppb_shift = (this->erase_shift - this->page_shift); + this->page_mask = (mtd->erasesize / mtd->oobblock) - 1; + + /* REVIST: Multichip handling */ + + mtd->size = this->chipsize; + + /* Version ID */ + version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); + printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id); + + /* Lock scheme */ + if (density <= ONENAND_DEVICE_DENSITY_512Mb && + !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) { + printk(KERN_INFO "Lock scheme is Continues Lock\n"); + this->options |= ONENAND_CONT_LOCK; + } + + return 0; +} + + +/** + * onenand_scan - [OneNAND Interface] Scan for the OneNAND device + * @param mtd MTD device structure + * @param maxchips Number of chips to scan for + * + * This fills out all the not initialized function pointers + * with the defaults. + * The flash ID is read and the mtd/chip structures are + * filled with the appropriate values. + */ +int onenand_scan(struct mtd_info *mtd, int maxchips) +{ + struct onenand_chip *this = mtd->priv; + + if (!this->read_word) + this->read_word = onenand_readw; + if (!this->write_word) + this->write_word = onenand_writew; + + if (!this->command) + this->command = onenand_command; + if (!this->wait) + this->wait = onenand_wait; + + if (!this->read_bufferram) + this->read_bufferram = onenand_read_bufferram; + if (!this->write_bufferram) + this->write_bufferram = onenand_write_bufferram; + + if (onenand_probe(mtd)) + return -ENXIO; + + this->state = FL_READY; + init_waitqueue_head(&this->wq); + spin_lock_init(&this->chip_lock); + + switch (mtd->oobsize) { + case 64: + this->autooob = &onenand_oob_64; + break; + + case 32: + this->autooob = &onenand_oob_32; + break; + + default: + printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", + mtd->oobsize); + /* To prevent kernel oops */ + this->autooob = &onenand_oob_32; + break; + } + + memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); + + /* Fill in remaining MTD driver data */ + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->ecctype = MTD_ECC_SW; + mtd->erase = onenand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = onenand_read; + mtd->write = onenand_write; + mtd->read_ecc = onenand_read_ecc; + mtd->write_ecc = onenand_write_ecc; + mtd->read_oob = onenand_read_oob; + mtd->write_oob = onenand_write_oob; + mtd->readv = NULL; + mtd->readv_ecc = NULL; + mtd->writev = onenand_writev; + mtd->writev_ecc = onenand_writev_ecc; + mtd->sync = onenand_sync; + mtd->lock = NULL; + mtd->unlock = onenand_unlock; + mtd->suspend = NULL; + mtd->resume = NULL; + mtd->block_isbad = onenand_block_isbad; + mtd->block_markbad = onenand_block_markbad; + mtd->owner = THIS_MODULE; + + /* Unlock whole block */ + mtd->unlock(mtd, 0x0, this->chipsize); + + return 0; +} + +/** + * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device + * @param mtd MTD device structure + */ +void onenand_release(struct mtd_info *mtd) +{ +#ifdef CONFIG_MTD_PARTITIONS + /* Deregister partitions */ + del_mtd_partitions (mtd); +#endif + /* Deregister the device */ + del_mtd_device (mtd); +} + +EXPORT_SYMBOL_GPL(onenand_scan); +EXPORT_SYMBOL_GPL(onenand_release); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Generic OneNAND flash driver code"); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h new file mode 100644 index 000000000000..b9a64117d646 --- /dev/null +++ b/include/linux/mtd/onenand.h @@ -0,0 +1,134 @@ +/* + * linux/include/linux/mtd/onenand.h + * + * Copyright (C) 2005 Samsung Electronics + * Kyungmin Park + * + * 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. + */ + +#ifndef __LINUX_MTD_ONENAND_H +#define __LINUX_MTD_ONENAND_H + +#include +#include + +#define MAX_BUFFERRAM 2 + +/* Scan and identify a OneNAND device */ +extern int onenand_scan(struct mtd_info *mtd, int max_chips); +/* Free resources held by the OneNAND device */ +extern void onenand_release(struct mtd_info *mtd); + +/** + * onenand_state_t - chip states + * Enumeration for OneNAND flash chip state + */ +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING, + FL_UNLOCKING, + FL_LOCKING, +} onenand_state_t; + +/** + * struct onenand_bufferram - OneNAND BufferRAM Data + * @param block block address in BufferRAM + * @param page page address in BufferRAM + * @param valid valid flag + */ +struct onenand_bufferram { + int block; + int page; + int valid; +}; + +/** + * struct onenand_chip - OneNAND Private Flash Chip Data + * @param base [BOARDSPECIFIC] address to access OneNAND + * @param chipsize [INTERN] the size of one chip for multichip arrays + * @param device_id [INTERN] device ID + * @param verstion_id [INTERN] version ID + * @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about + * @param erase_shift [INTERN] number of address bits in a block + * @param page_shift [INTERN] number of address bits in a page + * @param ppb_shift [INTERN] number of address bits in a pages per block + * @param page_mask [INTERN] a page per block mask + * @param bufferam_index [INTERN] BufferRAM index + * @param bufferam [INTERN] BufferRAM info + * @param readw [REPLACEABLE] hardware specific function for read short + * @param writew [REPLACEABLE] hardware specific function for write short + * @param command [REPLACEABLE] hardware specific function for writing commands to the chip + * @param wait [REPLACEABLE] hardware specific function for wait on ready + * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip + * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress + * @param state [INTERN] the current state of the OneNAND device + * @param autooob [REPLACEABLE] the default (auto)placement scheme + * @param priv [OPTIONAL] pointer to private chip date + */ +struct onenand_chip { + void __iomem *base; + unsigned int chipsize; + unsigned int device_id; + unsigned int options; + + unsigned int erase_shift; + unsigned int page_shift; + unsigned int ppb_shift; /* Pages per block shift */ + unsigned int page_mask; + + unsigned int bufferram_index; + struct onenand_bufferram bufferram[MAX_BUFFERRAM]; + + int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len); + int (*wait)(struct mtd_info *mtd, int state); + int (*read_bufferram)(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count); + int (*write_bufferram)(struct mtd_info *mtd, int area, + const unsigned char *buffer, int offset, size_t count); + unsigned short (*read_word)(void __iomem *addr); + void (*write_word)(unsigned short value, void __iomem *addr); + + spinlock_t chip_lock; + wait_queue_head_t wq; + onenand_state_t state; + + struct nand_oobinfo *autooob; + + void *priv; +}; + +#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) +#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) +#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) + +/* + * Options bits + */ +#define ONENAND_CONT_LOCK (0x0001) + + +/* + * OneNAND Flash Manufacturer ID Codes + */ +#define ONENAND_MFR_SAMSUNG 0xec +#define ONENAND_MFR_UNKNOWN 0x00 + +/** + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure + * @param name: Manufacturer name + * @param id: manufacturer ID code of device. +*/ +struct onenand_manufacturers { + int id; + char *name; +}; + +#endif /* __LINUX_MTD_ONENAND_H */ diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h new file mode 100644 index 000000000000..4a2daad7d738 --- /dev/null +++ b/include/linux/mtd/onenand_regs.h @@ -0,0 +1,167 @@ +/* + * linux/include/linux/mtd/onenand_regs.h + * + * OneNAND Register header file + * + * Copyright (C) 2005 Samsung Electronics + * + * 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. + */ + +#ifndef __ONENAND_REG_H +#define __ONENAND_REG_H + +/* Memory Address Map Translation (Word order) */ +#define ONENAND_MEMORY_MAP(x) ((x) << 1) + +/* + * External BufferRAM area + */ +#define ONENAND_BOOTRAM ONENAND_MEMORY_MAP(0x0000) +#define ONENAND_DATARAM ONENAND_MEMORY_MAP(0x0200) +#define ONENAND_SPARERAM ONENAND_MEMORY_MAP(0x8010) + +/* + * OneNAND Registers + */ +#define ONENAND_REG_MANUFACTURER_ID ONENAND_MEMORY_MAP(0xF000) +#define ONENAND_REG_DEVICE_ID ONENAND_MEMORY_MAP(0xF001) +#define ONENAND_REG_VERSION_ID ONENAND_MEMORY_MAP(0xF002) +#define ONENAND_REG_DATA_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF003) +#define ONENAND_REG_BOOT_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF004) +#define ONENAND_REG_NUM_BUFFERS ONENAND_MEMORY_MAP(0xF005) +#define ONENAND_REG_TECHNOLOGY ONENAND_MEMORY_MAP(0xF006) + +#define ONENAND_REG_START_ADDRESS1 ONENAND_MEMORY_MAP(0xF100) +#define ONENAND_REG_START_ADDRESS2 ONENAND_MEMORY_MAP(0xF101) +#define ONENAND_REG_START_ADDRESS3 ONENAND_MEMORY_MAP(0xF102) +#define ONENAND_REG_START_ADDRESS4 ONENAND_MEMORY_MAP(0xF103) +#define ONENAND_REG_START_ADDRESS5 ONENAND_MEMORY_MAP(0xF104) +#define ONENAND_REG_START_ADDRESS6 ONENAND_MEMORY_MAP(0xF105) +#define ONENAND_REG_START_ADDRESS7 ONENAND_MEMORY_MAP(0xF106) +#define ONENAND_REG_START_ADDRESS8 ONENAND_MEMORY_MAP(0xF107) + +#define ONENAND_REG_START_BUFFER ONENAND_MEMORY_MAP(0xF200) +#define ONENAND_REG_COMMAND ONENAND_MEMORY_MAP(0xF220) +#define ONENAND_REG_SYS_CFG1 ONENAND_MEMORY_MAP(0xF221) +#define ONENAND_REG_SYS_CFG2 ONENAND_MEMORY_MAP(0xF222) +#define ONENAND_REG_CTRL_STATUS ONENAND_MEMORY_MAP(0xF240) +#define ONENAND_REG_INTERRUPT ONENAND_MEMORY_MAP(0xF241) +#define ONENAND_REG_START_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24C) +#define ONENAND_REG_END_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24D) +#define ONENAND_REG_WP_STATUS ONENAND_MEMORY_MAP(0xF24E) + +#define ONENAND_REG_ECC_STATUS ONENAND_MEMORY_MAP(0xFF00) +#define ONENAND_REG_ECC_M0 ONENAND_MEMORY_MAP(0xFF01) +#define ONENAND_REG_ECC_S0 ONENAND_MEMORY_MAP(0xFF02) +#define ONENAND_REG_ECC_M1 ONENAND_MEMORY_MAP(0xFF03) +#define ONENAND_REG_ECC_S1 ONENAND_MEMORY_MAP(0xFF04) +#define ONENAND_REG_ECC_M2 ONENAND_MEMORY_MAP(0xFF05) +#define ONENAND_REG_ECC_S2 ONENAND_MEMORY_MAP(0xFF06) +#define ONENAND_REG_ECC_M3 ONENAND_MEMORY_MAP(0xFF07) +#define ONENAND_REG_ECC_S3 ONENAND_MEMORY_MAP(0xFF08) + +/* + * Device ID Register F001h (R) + */ +#define ONENAND_DEVICE_DENSITY_SHIFT (4) +#define ONENAND_DEVICE_IS_DDP (1 << 3) +#define ONENAND_DEVICE_IS_DEMUX (1 << 2) +#define ONENAND_DEVICE_VCC_MASK (0x3) + +#define ONENAND_DEVICE_DENSITY_512Mb (0x002) + +/* + * Version ID Register F002h (R) + */ +#define ONENAND_VERSION_PROCESS_SHIFT (8) + +/* + * Start Address 1 F100h (R/W) + */ +#define ONENAND_DDP_SHIFT (15) + +/* + * Start Address 8 F107h (R/W) + */ +#define ONENAND_FPA_MASK (0x3f) +#define ONENAND_FPA_SHIFT (2) +#define ONENAND_FSA_MASK (0x03) + +/* + * Start Buffer Register F200h (R/W) + */ +#define ONENAND_BSA_MASK (0x03) +#define ONENAND_BSA_SHIFT (8) +#define ONENAND_BSA_BOOTRAM (0 << 2) +#define ONENAND_BSA_DATARAM0 (2 << 2) +#define ONENAND_BSA_DATARAM1 (3 << 2) +#define ONENAND_BSC_MASK (0x03) + +/* + * Command Register F220h (R/W) + */ +#define ONENAND_CMD_READ (0x00) +#define ONENAND_CMD_READOOB (0x13) +#define ONENAND_CMD_PROG (0x80) +#define ONENAND_CMD_PROGOOB (0x1A) +#define ONENAND_CMD_UNLOCK (0x23) +#define ONENAND_CMD_LOCK (0x2A) +#define ONENAND_CMD_LOCK_TIGHT (0x2C) +#define ONENAND_CMD_ERASE (0x94) +#define ONENAND_CMD_RESET (0xF0) +#define ONENAND_CMD_READID (0x90) + +/* NOTE: Those are not *REAL* commands */ +#define ONENAND_CMD_BUFFERRAM (0x1978) + +/* + * System Configuration 1 Register F221h (R, R/W) + */ +#define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) +#define ONENAND_SYS_CFG1_BRL (1 << 12) +#define ONENAND_SYS_CFG1_BL (1 << 9) +#define ONENAND_SYS_CFG1_NO_ECC (1 << 8) +#define ONENAND_SYS_CFG1_RDY (1 << 7) +#define ONENAND_SYS_CFG1_INT (1 << 6) +#define ONENAND_SYS_CFG1_IOBE (1 << 5) +#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4) + +/* + * Controller Status Register F240h (R) + */ +#define ONENAND_CTRL_ONGO (1 << 15) +#define ONENAND_CTRL_LOCK (1 << 14) +#define ONENAND_CTRL_LOAD (1 << 13) +#define ONENAND_CTRL_PROGRAM (1 << 12) +#define ONENAND_CTRL_ERASE (1 << 11) +#define ONENAND_CTRL_ERROR (1 << 10) +#define ONENAND_CTRL_RSTB (1 << 7) + +/* + * Interrupt Status Register F241h (R) + */ +#define ONENAND_INT_MASTER (1 << 15) +#define ONENAND_INT_READ (1 << 7) +#define ONENAND_INT_WRITE (1 << 6) +#define ONENAND_INT_ERASE (1 << 5) +#define ONENAND_INT_RESET (1 << 4) +#define ONENAND_INT_CLEAR (0 << 0) + +/* + * NAND Flash Write Protection Status Register F24Eh (R) + */ +#define ONENAND_WP_US (1 << 2) +#define ONENAND_WP_LS (1 << 1) +#define ONENAND_WP_LTS (1 << 0) + +/* + * ECC Status Reigser FF00h (R) + */ +#define ONENAND_ECC_1BIT (1 << 0) +#define ONENAND_ECC_2BIT (1 << 1) +#define ONENAND_ECC_2BIT_ALL (0xAAAA) + +#endif /* __ONENAND_REG_H */ -- cgit v1.2.3 From 52b0eea73de05df33c51ca652e288a3ba1bba03b Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:07:19 +0100 Subject: [PATCH] OneNAND: Sync. Burst Read support Add OneNAND Sync. Burst Read support Tested with OMAP platform Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 6 ++++ drivers/mtd/onenand/omap-onenand.c | 66 ++++++++++++++++++++++++++++++++++++-- drivers/mtd/onenand/onenand_base.c | 39 ++++++++++++++++++++-- include/linux/mtd/onenand.h | 1 + include/linux/mtd/onenand_regs.h | 17 ++++++++-- 5 files changed, 123 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 7d76ede984d8..186ea9dc0942 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -29,4 +29,10 @@ config MTD_ONENAND_OMAP help Support for OneNAND flash on TI OMAP board. +config MTD_ONENAND_SYNC_READ + bool "OneNAND Sync. Burst Read Support" + depends on ARCH_OMAP + help + This enables support for Sync. Burst Read. + endmenu diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 56e1aec6b835..7c89549f7f58 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c @@ -25,9 +25,10 @@ #include #include #include +#include #define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS -#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS +#define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() /* * MTD structure for OMAP board */ @@ -68,10 +69,66 @@ static struct mtd_partition static_partition[] = { }, }; -const char *part_probes[] = { "cmdlinepart", NULL, }; +static const char *part_probes[] = { "cmdlinepart", NULL, }; #endif +#ifdef CONFIG_MTD_ONENAND_SYNC_READ +static unsigned int omap_emifs_cs; + +static void omap_find_emifs_cs(unsigned int addr) +{ + /* Check CS3 */ + if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { + omap_emifs_cs = 3; + } else { + omap_emifs_cs = (addr >> 26); + } +} + +/** + * omap_onenand_mmcontrol - Control OMAP EMIFS + */ +static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) +{ + struct onenand_chip *this = mtd->priv; + static unsigned long omap_emifs_ccs, omap_emifs_acs; + static unsigned long onenand_sys_cfg1; + int config, emifs_ccs, emifs_acs; + + if (sync_read) { + /* + * Note: BRL and RDWST is equal + */ + omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); + omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); + + emifs_ccs = 0x41141; + emifs_acs = 0x1; + + /* OneNAND System Configuration 1 */ + onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); + config = (onenand_sys_cfg1 + & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) + | ONENAND_SYS_CFG1_SYNC_READ + | ONENAND_SYS_CFG1_BRL_4 + | ONENAND_SYS_CFG1_BL_8; + } else { + emifs_ccs = omap_emifs_ccs; + emifs_acs = omap_emifs_acs; + config = onenand_sys_cfg1; + } + + this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); + EMIFS_CCS(omap_emifs_cs) = emifs_ccs; + EMIFS_ACS(omap_emifs_cs) = emifs_acs; +} +#else +#define omap_find_emifs_cs(x) do { } while (0) +#define omap_onenand_mmcontrol NULL +#endif + + /* Scan to find existance of the device at base. This also allocates oob and data internal buffers */ static char onenand_name[] = "onenand"; @@ -102,14 +159,19 @@ static int __init omap_onenand_init (void) /* Link the private data with the MTD structure */ omap_onenand_mtd->priv = this; + this->mmcontrol = omap_onenand_mmcontrol; /* try the first address */ this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); + omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); + omap_onenand_mtd->name = onenand_name; if (onenand_scan(omap_onenand_mtd, 1)){ /* try the second address */ iounmap(this->base); this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); + omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); + if (onenand_scan(omap_onenand_mtd, 1)) { iounmap(this->base); err = -ENXIO; diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bcce22ae3cb1..e87489505772 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -378,6 +378,35 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area, return 0; } +/** + * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Read the BufferRAM area with Sync. Burst Mode + */ +static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ); + + memcpy(buffer, bufferram + offset, count); + + this->mmcontrol(mtd, 0); + + return 0; +} + /** * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area * @param mtd MTD data structure @@ -1273,8 +1302,8 @@ static int onenand_check_maf(int manuf) break; } - printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", - onenand_manuf_ids[i].name); + printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", + onenand_manuf_ids[i].name, manuf); return (i != ONENAND_MFR_UNKNOWN); } @@ -1385,6 +1414,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (onenand_probe(mtd)) return -ENXIO; + /* Set Sync. Burst Read after probing */ + if (this->mmcontrol) { + printk(KERN_INFO "OneNAND Sync. Burst Read support\n"); + this->read_bufferram = onenand_sync_read_bufferram; + } + this->state = FL_READY; init_waitqueue_head(&this->wq); spin_lock_init(&this->chip_lock); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index b9a64117d646..c557caa24a6c 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -95,6 +95,7 @@ struct onenand_chip { const unsigned char *buffer, int offset, size_t count); unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); + void (*mmcontrol)(struct mtd_info *mtd, int sync_read); spinlock_t chip_lock; wait_queue_head_t wq; diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index 4a2daad7d738..d7832ef8ed63 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h @@ -121,8 +121,21 @@ * System Configuration 1 Register F221h (R, R/W) */ #define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) -#define ONENAND_SYS_CFG1_BRL (1 << 12) -#define ONENAND_SYS_CFG1_BL (1 << 9) +#define ONENAND_SYS_CFG1_BRL_7 (7 << 12) +#define ONENAND_SYS_CFG1_BRL_6 (6 << 12) +#define ONENAND_SYS_CFG1_BRL_5 (5 << 12) +#define ONENAND_SYS_CFG1_BRL_4 (4 << 12) +#define ONENAND_SYS_CFG1_BRL_3 (3 << 12) +#define ONENAND_SYS_CFG1_BRL_10 (2 << 12) +#define ONENAND_SYS_CFG1_BRL_9 (1 << 12) +#define ONENAND_SYS_CFG1_BRL_8 (0 << 12) +#define ONENAND_SYS_CFG1_BRL_SHIFT (12) +#define ONENAND_SYS_CFG1_BL_32 (4 << 9) +#define ONENAND_SYS_CFG1_BL_16 (3 << 9) +#define ONENAND_SYS_CFG1_BL_8 (2 << 9) +#define ONENAND_SYS_CFG1_BL_4 (1 << 9) +#define ONENAND_SYS_CFG1_BL_CONT (0 << 9) +#define ONENAND_SYS_CFG1_BL_SHIFT (9) #define ONENAND_SYS_CFG1_NO_ECC (1 << 8) #define ONENAND_SYS_CFG1_RDY (1 << 7) #define ONENAND_SYS_CFG1_INT (1 << 6) -- cgit v1.2.3 From cdc001305da4f057353911018e28f26f8f879061 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:15:48 +0100 Subject: [PATCH] OneNAND: Simple Bad Block handling support Based on NAND memory bad block table code Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Makefile | 4 +- drivers/mtd/onenand/onenand_base.c | 105 ++++++++++++++++++++++++++++++------- include/linux/mtd/onenand.h | 9 ++++ 3 files changed, 98 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index f4e75864d8b5..243c7592a111 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -3,7 +3,9 @@ # # Core functionality. -obj-$(CONFIG_MTD_ONENAND) += onenand_base.o +obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o + +onenand-objs = onenand_base.o onenand_bbt.o diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index e87489505772..bdeac01e659f 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -311,19 +311,21 @@ static int onenand_wait(struct mtd_info *mtd, int state) ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ERROR) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); - return -EIO; + /* It maybe occur at initial bad block */ + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); + /* Clear other interrupt bits for preventing ECC error */ + interrupt &= ONENAND_INT_MASTER; } if (ctrl & ONENAND_CTRL_LOCK) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); - return -EIO; + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl); + return -EACCES; } if (interrupt & ONENAND_INT_READ) { ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); if (ecc & ONENAND_ECC_2BIT_ALL) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); return -EBADMSG; } } @@ -1059,6 +1061,25 @@ static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); } +/** + * onenand_block_checkbad - [GENERIC] Check if a block is marked bad + * @param mtd MTD device structure + * @param ofs offset from device start + * @param getchip 0, if the chip is already selected + * @param allowbbt 1, if its allowed to access the bbt area + * + * Check, if the block is bad. Either by reading the bad block table or + * calling of the scan function. + */ +static int onenand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + + /* Return info from the table */ + return bbm->isbad_bbt(mtd, ofs, allowbbt); +} + /** * onenand_erase - [MTD Interface] erase block(s) * @param mtd MTD device structure @@ -1109,7 +1130,12 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { - /* TODO Check badblock */ + /* Check if we have a bad block, we do not erase bad blocks */ + if (onenand_block_checkbad(mtd, addr, 0, 0)) { + printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr); + instr->state = MTD_ERASE_FAILED; + goto erase_exit; + } this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); @@ -1161,34 +1187,70 @@ static void onenand_sync(struct mtd_info *mtd) onenand_release_device(mtd); } + /** * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad * @param mtd MTD device structure * @param ofs offset relative to mtd start + * + * Check whether the block is bad */ static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) { - /* - * TODO - * 1. Bad block table (BBT) - * -> using NAND BBT to support JFFS2 - * 2. Bad block management (BBM) - * -> bad block replace scheme - * - * Currently we do nothing - */ - return 0; + /* Check for invalid offset */ + if (ofs > mtd->size) + return -EINVAL; + + return onenand_block_checkbad(mtd, ofs, 1, 0); +} + +/** + * onenand_default_block_markbad - [DEFAULT] mark a block bad + * @param mtd MTD device structure + * @param ofs offset from device start + * + * This is the default implementation, which can be overridden by + * a hardware specific driver. + */ +static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + u_char buf[2] = {0, 0}; + size_t retlen; + int block; + + /* Get block number */ + block = ((int) ofs) >> bbm->bbt_erase_shift; + if (bbm->bbt) + bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + + /* We write two bytes, so we dont have to mess with 16 bit access */ + ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); + return mtd->write_oob(mtd, ofs , 2, &retlen, buf); } /** * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad * @param mtd MTD device structure * @param ofs offset relative to mtd start + * + * Mark the block as bad */ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - /* see above */ - return 0; + struct onenand_chip *this = mtd->priv; + int ret; + + ret = onenand_block_isbad(mtd, ofs); + if (ret) { + /* If it was bad already, return success and do nothing */ + if (ret > 0) + return 0; + return ret; + } + + return this->block_markbad(mtd, ofs); } /** @@ -1411,6 +1473,11 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (!this->write_bufferram) this->write_bufferram = onenand_write_bufferram; + if (!this->block_markbad) + this->block_markbad = onenand_default_block_markbad; + if (!this->scan_bbt) + this->scan_bbt = onenand_default_bbt; + if (onenand_probe(mtd)) return -ENXIO; @@ -1472,7 +1539,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) /* Unlock whole block */ mtd->unlock(mtd, 0x0, this->chipsize); - return 0; + return this->scan_bbt(mtd); } /** diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index c557caa24a6c..89aaffbc9576 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -14,6 +14,7 @@ #include #include +#include #define MAX_BUFFERRAM 2 @@ -67,10 +68,14 @@ struct onenand_bufferram { * @param wait [REPLACEABLE] hardware specific function for wait on ready * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param read_word [REPLACEABLE] hardware specific function for read register of OneNAND + * @param write_word [REPLACEABLE] hardware specific function for write register of OneNAND + * @param scan_bbt [REPLACEALBE] hardware specific function for scaning Bad block Table * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * @param state [INTERN] the current state of the OneNAND device * @param autooob [REPLACEABLE] the default (auto)placement scheme + * @param bbm [REPLACEABLE] pointer to Bad Block Management * @param priv [OPTIONAL] pointer to private chip date */ struct onenand_chip { @@ -96,6 +101,8 @@ struct onenand_chip { unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); void (*mmcontrol)(struct mtd_info *mtd, int sync_read); + int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); + int (*scan_bbt)(struct mtd_info *mtd); spinlock_t chip_lock; wait_queue_head_t wq; @@ -103,6 +110,8 @@ struct onenand_chip { struct nand_oobinfo *autooob; + void *bbm; + void *priv; }; -- cgit v1.2.3 From fcc31470c49e224ed8115c70541f599fc7568fee Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:20:08 +0100 Subject: [PATCH] OneNAND: Update OMAP OneNAND mapping using device driver model - Update OMAP OneNAND mapping file using device driver model - Remove board specific macro and values. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/omap-onenand.c | 271 ++++++++++++------------------------- include/linux/mtd/onenand.h | 8 ++ 2 files changed, 97 insertions(+), 182 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 7c89549f7f58..57e69f184d33 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c @@ -4,236 +4,143 @@ * Copyright (c) 2005 Samsung Electronics * Kyungmin Park * - * Derived from linux/drivers/mtd/nand/omap-nand-flash.c - * * 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. * * Overview: - * This is a device driver for the OneNAND flash device for TI OMAP boards. + * This is a device driver for the OneNAND flash for OMAP boards. */ -#include -#include +#include #include +#include #include #include #include #include -#include -#include -#include -#include +#include -#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS -#define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() -/* - * MTD structure for OMAP board - */ -static struct mtd_info *omap_onenand_mtd = NULL; +#define DRIVER_NAME "onenand" -/* - * Define partitions for flash devices - */ #ifdef CONFIG_MTD_PARTITIONS -static struct mtd_partition static_partition[] = { - { - .name = "X-Loader + U-Boot", - .offset = 0, - .size = SZ_128K, - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "U-Boot Environment", - .offset = MTDPART_OFS_APPEND, - .size = SZ_128K, - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "kernel", - .offset = MTDPART_OFS_APPEND, - .size = 2 * SZ_1M - }, - { - .name = "filesystem0", - .offset = MTDPART_OFS_APPEND, - .size = SZ_16M, - }, - { - .name = "filesystem1", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - static const char *part_probes[] = { "cmdlinepart", NULL, }; - #endif -#ifdef CONFIG_MTD_ONENAND_SYNC_READ -static unsigned int omap_emifs_cs; +struct omap_onenand_info { + struct mtd_info mtd; + struct mtd_partition *parts; + struct onenand_chip onenand; +}; -static void omap_find_emifs_cs(unsigned int addr) +static int __devinit omap_onenand_probe(struct device *dev) { - /* Check CS3 */ - if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { - omap_emifs_cs = 3; - } else { - omap_emifs_cs = (addr >> 26); + struct omap_onenand_info *info; + struct platform_device *pdev = to_platform_device(dev); + struct onenand_platform_data *pdata = pdev->dev.platform_data; + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; + int err; + + info = kmalloc(sizeof(struct omap_onenand_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memset(info, 0, sizeof(struct omap_onenand_info)); + + if (!request_mem_region(res->start, size, dev->driver->name)) { + err = -EBUSY; + goto out_free_info; } -} -/** - * omap_onenand_mmcontrol - Control OMAP EMIFS - */ -static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) -{ - struct onenand_chip *this = mtd->priv; - static unsigned long omap_emifs_ccs, omap_emifs_acs; - static unsigned long onenand_sys_cfg1; - int config, emifs_ccs, emifs_acs; - - if (sync_read) { - /* - * Note: BRL and RDWST is equal - */ - omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); - omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); - - emifs_ccs = 0x41141; - emifs_acs = 0x1; - - /* OneNAND System Configuration 1 */ - onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); - config = (onenand_sys_cfg1 - & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) - | ONENAND_SYS_CFG1_SYNC_READ - | ONENAND_SYS_CFG1_BRL_4 - | ONENAND_SYS_CFG1_BL_8; - } else { - emifs_ccs = omap_emifs_ccs; - emifs_acs = omap_emifs_acs; - config = onenand_sys_cfg1; + info->onenand.base = ioremap(res->start, size); + if (!info->onenand.base) { + err = -ENOMEM; + goto out_release_mem_region; } - this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); - EMIFS_CCS(omap_emifs_cs) = emifs_ccs; - EMIFS_ACS(omap_emifs_cs) = emifs_acs; -} -#else -#define omap_find_emifs_cs(x) do { } while (0) -#define omap_onenand_mmcontrol NULL -#endif + info->onenand.mmcontrol = pdata->mmcontrol; + info->mtd.name = pdev->dev.bus_id; + info->mtd.priv = &info->onenand; + info->mtd.owner = THIS_MODULE; -/* Scan to find existance of the device at base. - This also allocates oob and data internal buffers */ -static char onenand_name[] = "onenand"; - -/* - * Main initialization routine - */ -static int __init omap_onenand_init (void) -{ - struct onenand_chip *this; - struct mtd_partition *dynamic_partition = 0; - int err = 0; - - /* Allocate memory for MTD device structure and private data */ - omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), - GFP_KERNEL); - if (!omap_onenand_mtd) { - printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); - err = -ENOMEM; - goto out; + if (onenand_scan(&info->mtd, 1)) { + err = -ENXIO; + goto out_iounmap; } - /* Get pointer to private data */ - this = (struct onenand_chip *) (&omap_onenand_mtd[1]); +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); + if (err > 0) + add_mtd_partitions(&info->mtd, info->parts, err); + else if (err < 0 && pdata->parts) + add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); + else +#endif + err = add_mtd_device(&info->mtd); - /* Initialize structures */ - memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); + dev_set_drvdata(&pdev->dev, info); - /* Link the private data with the MTD structure */ - omap_onenand_mtd->priv = this; - this->mmcontrol = omap_onenand_mmcontrol; + return 0; - /* try the first address */ - this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); - omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); +out_iounmap: + iounmap(info->onenand.base); +out_release_mem_region: + release_mem_region(res->start, size); +out_free_info: + kfree(info); - omap_onenand_mtd->name = onenand_name; - if (onenand_scan(omap_onenand_mtd, 1)){ - /* try the second address */ - iounmap(this->base); - this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); - omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); + return err; +} - if (onenand_scan(omap_onenand_mtd, 1)) { - iounmap(this->base); - err = -ENXIO; - goto out_mtd; - } - } +static int __devexit omap_onenand_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_onenand_info *info = dev_get_drvdata(&pdev->dev); + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; - /* Register the partitions */ - switch (omap_onenand_mtd->size) { - case SZ_128M: - case SZ_64M: - case SZ_32M: -#ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(omap_onenand_mtd, part_probes, - &dynamic_partition, 0); - if (err > 0) - err = add_mtd_partitions(omap_onenand_mtd, - dynamic_partition, err); - else if (1) - err = add_mtd_partitions(omap_onenand_mtd, - static_partition, - ARRAY_SIZE(static_partition)); + dev_set_drvdata(&pdev->dev, NULL); + + if (info) { + if (info->parts) + del_mtd_partitions(&info->mtd); else -#endif - err = add_mtd_device(omap_onenand_mtd); - if (err) - goto out_buf; - break; + del_mtd_device(&info->mtd); - default: - printk(KERN_WARNING "Unsupported OneNAND device\n"); - err = -ENXIO; - goto out_buf; + onenand_release(&info->mtd); + release_mem_region(res->start, size); + iounmap(info->onenand.base); + kfree(info); } return 0; - -out_buf: - onenand_release(omap_onenand_mtd); - iounmap(this->base); -out_mtd: - kfree(omap_onenand_mtd); -out: - return err; } -/* - * Clean up routine - */ -static void __exit omap_onenand_cleanup (void) +static struct device_driver omap_onenand_driver = { + .name = DRIVER_NAME, + .bus = &platform_bus_type, + .probe = omap_onenand_probe, + .remove = __devexit_p(omap_onenand_remove), +}; + +MODULE_ALIAS(DRIVER_NAME); + +static int __init omap_onenand_init(void) { - struct onenand_chip *this = omap_onenand_mtd->priv; + return driver_register(&omap_onenand_driver); +} - /* onenand_release frees MTD partitions, MTD structure - and onenand internal buffers */ - onenand_release(omap_onenand_mtd); - iounmap(this->base); - kfree(omap_onenand_mtd); +static void __exit omap_onenand_exit(void) +{ + driver_unregister(&omap_onenand_driver); } module_init(omap_onenand_init); -module_exit(omap_onenand_cleanup); +module_exit(omap_onenand_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kyungmin Park "); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 89aaffbc9576..2c29a5ca2c91 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -115,10 +115,18 @@ struct onenand_chip { void *priv; }; +/* + * Helper macros + */ #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) +#define ONENAND_GET_SYS_CFG1(this) \ + (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) +#define ONENAND_SET_SYS_CFG1(v, this) \ + (this->write_word(v, this->base + ONENAND_REG_SYS_CFG1)) + /* * Options bits */ -- cgit v1.2.3 From d36d63d404b75ddf231da0dbd3640e6d1722b4ab Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:36:21 +0100 Subject: [PATCH] OneNAND: Fix bug in write verify - Remove unused block, page parameters - Add constant instead of runtime value Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 11 ++++------- include/linux/mtd/onenand.h | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bdeac01e659f..75d757882697 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -719,13 +719,10 @@ out: * onenand_verify_page - [GENERIC] verify the chip contents after a write * @param mtd MTD device structure * @param buf the databuffer to verify - * @param block block address - * @param page page address * * Check DataRAM area directly */ -static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, - loff_t addr, int block, int page) +static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr) { struct onenand_chip *this = mtd->priv; void __iomem *dataram0, *dataram1; @@ -816,7 +813,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, written += thislen; /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); + ret = onenand_verify_page(mtd, (u_char *) buf, to); if (ret) { DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); goto out; @@ -940,7 +937,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, u_char *eccbuf, struct nand_oobinfo *oobsel) { struct onenand_chip *this = mtd->priv; - unsigned char buffer[mtd->oobblock], *pbuf; + unsigned char buffer[MAX_ONENAND_PAGESIZE], *pbuf; size_t total_len, len; int i, written = 0; int ret = 0; @@ -1025,7 +1022,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); + ret = onenand_verify_page(mtd, (u_char *) pbuf, to); if (ret) { DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); goto out; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 2c29a5ca2c91..58023082320a 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -17,6 +17,7 @@ #include #define MAX_BUFFERRAM 2 +#define MAX_ONENAND_PAGESIZE (2048 + 64) /* Scan and identify a OneNAND device */ extern int onenand_scan(struct mtd_info *mtd, int max_chips); -- cgit v1.2.3 From e631ddba588783edd521c5a89f7b2902772fb691 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Wed, 7 Sep 2005 09:35:26 +0100 Subject: [JFFS2] Add erase block summary support (mount time improvement) The goal of summary is to speed up the mount time. Erase block summary (EBS) stores summary information at the end of every (closed) erase block. It is no longer necessary to scan all nodes separetly (and read all pages of them) just read this "small" summary, where every information is stored which is needed at mount time. This summary information is stored in a JFFS2_FEATURE_RWCOMPAT_DELETE. During the mount process if there is no summary info the orignal scan process will be executed. EBS works with NAND and NOR flashes, too. There is a user space tool called sumtool to generate this summary information for a JFFS2 image. Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/Kconfig | 13 + fs/jffs2/Makefile | 3 +- fs/jffs2/build.c | 12 +- fs/jffs2/debug.h | 10 +- fs/jffs2/dir.c | 20 +- fs/jffs2/file.c | 5 +- fs/jffs2/fs.c | 5 +- fs/jffs2/gc.c | 26 +- fs/jffs2/nodelist.h | 13 +- fs/jffs2/nodemgmt.c | 250 ++++++++++----- fs/jffs2/os-linux.h | 19 +- fs/jffs2/scan.c | 198 ++++++++---- fs/jffs2/summary.c | 729 ++++++++++++++++++++++++++++++++++++++++++++ fs/jffs2/summary.h | 183 +++++++++++ fs/jffs2/super.c | 8 +- fs/jffs2/wbuf.c | 12 +- fs/jffs2/write.c | 29 +- fs/jffs2/writev.c | 34 ++- include/linux/jffs2.h | 21 +- include/linux/jffs2_fs_sb.h | 4 +- 20 files changed, 1395 insertions(+), 199 deletions(-) create mode 100644 fs/jffs2/summary.c create mode 100644 fs/jffs2/summary.h (limited to 'include') diff --git a/fs/Kconfig b/fs/Kconfig index 01a295232f75..37d86c5072eb 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1050,6 +1050,19 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash +config JFFS2_SUMMARY + bool "JFFS2 summary support (EXPERIMENTAL)" + depends on JFFS2_FS && EXPERIMENTAL + default n + help + This feature makes it possible to use summary information + for faster filesystem mount. + + The summary information can be inserted into a filesystem image + by the utility 'sumtool'. + + If unsure, say 'N'. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" depends on JFFS2_FS diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile index e6230f1bba73..77dc5561a04e 100644 --- a/fs/jffs2/Makefile +++ b/fs/jffs2/Makefile @@ -1,7 +1,7 @@ # # Makefile for the Linux Journalling Flash File System v2 (JFFS2) # -# $Id: Makefile.common,v 1.10 2005/07/17 06:56:20 dedekind Exp $ +# $Id: Makefile.common,v 1.11 2005/09/07 08:34:53 havasi Exp $ # obj-$(CONFIG_JFFS2_FS) += jffs2.o @@ -15,3 +15,4 @@ jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o +jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 1522eace932e..f4a47a3b2a01 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.77 2005/08/31 13:51:00 havasi Exp $ + * $Id: build.c,v 1.78 2005/09/07 08:34:54 havasi Exp $ * */ @@ -350,6 +350,10 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) INIT_LIST_HEAD(&c->bad_list); INIT_LIST_HEAD(&c->bad_used_list); c->highest_ino = 1; + c->summary = NULL; + + if (jffs2_sum_init(c)) + return -ENOMEM; if (jffs2_build_filesystem(c)) { D1(printk(KERN_DEBUG "build_fs failed\n")); @@ -357,11 +361,11 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) jffs2_free_raw_node_refs(c); #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) - vfree(c->blocks); + vfree(c->blocks); else #endif - kfree(c->blocks); - + kfree(c->blocks); + return -EIO; } diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 03d9626ad1ce..60e5dbb3946a 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.14 2005/08/17 13:48:59 dedekind Exp $ + * $Id: debug.h,v 1.15 2005/09/07 08:34:54 havasi Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -28,6 +28,7 @@ #define JFFS2_DBG_DENTLIST_MESSAGES #define JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_INOCACHE_MESSAGES +#define JFFS2_DBG_SUMMARY_MESSAGES #endif #if CONFIG_JFFS2_FS_DEBUG == 2 @@ -137,6 +138,13 @@ #define JFFS2_DBG_INOCACHE(fmt, ...) #endif +/* Summary debugging messages */ +#ifdef JFFS2_DBG_SUMMARY_MESSAGES +#define JFFS2_DBG_SUMMARY(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_SUMMARY(fmt, ...) +#endif + /* Watch the object allocations */ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES #define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 0fd15aaf2458..19bea0f95ac1 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $ + * $Id: dir.c,v 1.89 2005/09/07 08:34:54 havasi Exp $ * */ @@ -310,7 +310,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -370,7 +371,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -455,7 +457,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -498,7 +501,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -607,7 +611,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -652,7 +657,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 8279bf0133ff..231404a74728 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.102 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: file.c,v 1.103 2005/09/07 08:34:54 havasi Exp $ * */ @@ -134,7 +134,8 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); - ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) return ret; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index c99451ae4b77..c15c30220475 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.64 2005/09/01 08:42:31 havasi Exp $ + * $Id: fs.c,v 1.65 2005/09/07 08:34:54 havasi Exp $ * */ @@ -74,7 +74,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) return -ENOMEM; } - ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); if (S_ISLNK(inode->i_mode & S_IFMT)) diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index def97157ecbd..ee54cdc59e06 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $ + * $Id: gc.c,v 1.154 2005/09/07 08:34:54 havasi Exp $ * */ @@ -513,8 +513,11 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, /* Ask for a small amount of space (or the totlen if smaller) because we don't want to force wastage of the end of a block if splitting would work. */ - ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, - rawlen), &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + + JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); + /* this is not the exact summary size of it, + it is only an upper estimation */ + if (ret) return ret; @@ -622,7 +625,9 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); - ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen); + /* this is not the exact summary size of it, + it is only an upper estimation */ if (!ret) { D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); @@ -701,7 +706,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ } - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", sizeof(ri)+ mdatalen, ret); @@ -781,7 +787,8 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, + JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", sizeof(rd)+rd.nsize, ret); @@ -994,7 +1001,8 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.data_crc = cpu_to_je32(0); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", sizeof(ri), ret); @@ -1219,7 +1227,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era uint32_t cdatalen; uint16_t comprtype = JFFS2_COMPR_NONE; - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", @@ -1276,4 +1285,3 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era jffs2_gc_release_page(c, pg_ptr, &pg); return ret; } - diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1533af8b3959..1222372cb290 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.139 2005/08/31 13:51:00 havasi Exp $ + * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $ * */ @@ -20,6 +20,7 @@ #include #include #include +#include "summary.h" #ifdef __ECOS #include "os-ecos.h" @@ -326,8 +327,10 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, int prio, uint32_t sumsize); +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, uint32_t sumsize); int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); @@ -386,6 +389,10 @@ char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); /* scan.c */ int jffs2_scan_medium(struct jffs2_sb_info *c); void jffs2_rotate_lists(struct jffs2_sb_info *c); +int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf, + uint32_t ofs, uint32_t len); +struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); +int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); /* build.c */ int jffs2_do_mount_fs(struct jffs2_sb_info *c); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index fe7e70a4055b..208b2bdf01e5 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.124 2005/07/20 15:32:28 dedekind Exp $ + * $Id: nodemgmt.c,v 1.125 2005/09/07 08:34:54 havasi Exp $ * */ @@ -17,6 +17,7 @@ #include #include /* For cond_resched() */ #include "nodelist.h" +#include "debug.h" /** * jffs2_reserve_space - request physical space to write nodes to flash @@ -38,9 +39,11 @@ * for the requested allocation. */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, + uint32_t *ofs, uint32_t *len, uint32_t sumsize); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio) +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, int prio, uint32_t sumsize) { int ret = -EAGAIN; int blocksneeded = c->resv_blocks_write; @@ -129,7 +132,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs spin_lock(&c->erase_completion_lock); } - ret = jffs2_do_reserve_space(c, minsize, ofs, len); + ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); } @@ -140,7 +143,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs return ret; } -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, uint32_t sumsize) { int ret = -EAGAIN; minsize = PAD(minsize); @@ -149,7 +153,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * spin_lock(&c->erase_completion_lock); while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len); + ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); } @@ -158,105 +162,183 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * return ret; } -/* Called with alloc sem _and_ erase_completion_lock */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) + +/* Classify nextblock (clean, dirty of verydirty) and force to select an other one */ + +static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { - struct jffs2_eraseblock *jeb = c->nextblock; + + /* Check, if we have a dirty block now, or if it was dirty already */ + if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { + c->dirty_size += jeb->wasted_size; + c->wasted_size -= jeb->wasted_size; + jeb->dirty_size += jeb->wasted_size; + jeb->wasted_size = 0; + if (VERYDIRTY(c, jeb->dirty_size)) { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->very_dirty_list); + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->dirty_list); + } + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->clean_list); + } + c->nextblock = NULL; + +} + +/* Select a new jeb for nextblock */ + +static int jffs2_find_nextblock(struct jffs2_sb_info *c) +{ + struct list_head *next; - restart: - if (jeb && minsize > jeb->free_size) { - /* Skip the end of this block and file it as having some dirty space */ - /* If there's a pending write to it, flush now */ - if (jffs2_wbuf_dirty(c)) { + /* Take the next block off the 'free' list */ + + if (list_empty(&c->free_list)) { + + if (!c->nr_erasing_blocks && + !list_empty(&c->erasable_list)) { + struct jffs2_eraseblock *ejeb; + + ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); + list_del(&ejeb->list); + list_add_tail(&ejeb->list, &c->erase_pending_list); + c->nr_erasing_blocks++; + jffs2_erase_pending_trigger(c); + D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n", + ejeb->offset)); + } + + if (!c->nr_erasing_blocks && + !list_empty(&c->erasable_pending_wbuf_list)) { + D1(printk(KERN_DEBUG "jffs2_find_nextblock: Flushing write buffer\n")); + /* c->nextblock is NULL, no update to c->nextblock allowed */ spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); jffs2_flush_wbuf_pad(c); spin_lock(&c->erase_completion_lock); - jeb = c->nextblock; - goto restart; + /* Have another go. It'll be on the erasable_list now */ + return -EAGAIN; } - c->wasted_size += jeb->free_size; - c->free_size -= jeb->free_size; - jeb->wasted_size += jeb->free_size; - jeb->free_size = 0; - - /* Check, if we have a dirty block now, or if it was dirty already */ - if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { - c->dirty_size += jeb->wasted_size; - c->wasted_size -= jeb->wasted_size; - jeb->dirty_size += jeb->wasted_size; - jeb->wasted_size = 0; - if (VERYDIRTY(c, jeb->dirty_size)) { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->very_dirty_list); - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); - } - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->clean_list); + + if (!c->nr_erasing_blocks) { + /* Ouch. We're in GC, or we wouldn't have got here. + And there's no space left. At all. */ + printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", + c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", + list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); + return -ENOSPC; } - c->nextblock = jeb = NULL; + + spin_unlock(&c->erase_completion_lock); + /* Don't wait for it; just erase one right now */ + jffs2_erase_pending_blocks(c, 1); + spin_lock(&c->erase_completion_lock); + + /* An erase may have failed, decreasing the + amount of free space available. So we must + restart from the beginning */ + return -EAGAIN; } + + next = c->free_list.next; + list_del(next); + c->nextblock = list_entry(next, struct jffs2_eraseblock, list); + c->nr_free_blocks--; - if (!jeb) { - struct list_head *next; - /* Take the next block off the 'free' list */ + jffs2_sum_reset_collected(c->summary); /* reset collected summary */ - if (list_empty(&c->free_list)) { + D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_list)) { - struct jffs2_eraseblock *ejeb; + return 0; +} - ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); - list_del(&ejeb->list); - list_add_tail(&ejeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", - ejeb->offset)); +/* Called with alloc sem _and_ erase_completion_lock */ +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize) +{ + struct jffs2_eraseblock *jeb = c->nextblock; + uint32_t reserved_size; /* for summary information at the end of the jeb */ + int ret; + + restart: + reserved_size = 0; + + if (jffs2_sum_active() && (sumsize != JFFS2_SUMMARY_NOSUM_SIZE)) { + /* NOSUM_SIZE means not to generate summary */ + + if (jeb) { + reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); + JFFS2_DBG_SUMMARY("minsize=%d , jeb->free=%d ," + "summary->size=%d , sumsize=%d\n", + minsize, jeb->free_size, + c->summary->sum_size, sumsize); + } + + /* Is there enough space for writing out the current node, or we have to + write out summary information now, close this jeb and select new nextblock? */ + if (jeb && (PAD(minsize) + PAD(c->summary->sum_size + sumsize + + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size)) { + + /* Has summary been disabled for this jeb? */ + if (jffs2_sum_is_disabled(c->summary)) { + sumsize = JFFS2_SUMMARY_NOSUM_SIZE; + goto restart; } - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_pending_wbuf_list)) { - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); - /* c->nextblock is NULL, no update to c->nextblock allowed */ + /* Writing out the collected summary information */ + JFFS2_DBG_SUMMARY("generating summary for 0x%08x.\n", jeb->offset); + ret = jffs2_sum_write_sumnode(c); + + if (ret) + return ret; + + if (jffs2_sum_is_disabled(c->summary)) { + /* jffs2_write_sumnode() couldn't write out the summary information + diabling summary for this jeb and free the collected information + */ + sumsize = JFFS2_SUMMARY_NOSUM_SIZE; + goto restart; + } + + jffs2_close_nextblock(c, jeb); + jeb = NULL; + } + } else { + if (jeb && minsize > jeb->free_size) { + /* Skip the end of this block and file it as having some dirty space */ + /* If there's a pending write to it, flush now */ + + if (jffs2_wbuf_dirty(c)) { spin_unlock(&c->erase_completion_lock); + D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); jffs2_flush_wbuf_pad(c); spin_lock(&c->erase_completion_lock); - /* Have another go. It'll be on the erasable_list now */ - return -EAGAIN; - } - - if (!c->nr_erasing_blocks) { - /* Ouch. We're in GC, or we wouldn't have got here. - And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", - list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); - return -ENOSPC; + jeb = c->nextblock; + goto restart; } - spin_unlock(&c->erase_completion_lock); - /* Don't wait for it; just erase one right now */ - jffs2_erase_pending_blocks(c, 1); - spin_lock(&c->erase_completion_lock); + c->wasted_size += jeb->free_size; + c->free_size -= jeb->free_size; + jeb->wasted_size += jeb->free_size; + jeb->free_size = 0; - /* An erase may have failed, decreasing the - amount of free space available. So we must - restart from the beginning */ - return -EAGAIN; + jffs2_close_nextblock(c, jeb); + jeb = NULL; } + } + + if (!jeb) { + + ret = jffs2_find_nextblock(c); + if (ret) + return ret; - next = c->free_list.next; - list_del(next); - c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); - c->nr_free_blocks--; + jeb = c->nextblock; if (jeb->free_size != c->sector_size - c->cleanmarker_size) { printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); @@ -266,7 +348,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has enough space */ *ofs = jeb->offset + (c->sector_size - jeb->free_size); - *len = jeb->free_size; + *len = jeb->free_size - reserved_size; if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index c3c1619fb137..e026888cf1cb 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.60 2005/08/06 04:51:30 nico Exp $ + * $Id: os-linux.h,v 1.61 2005/09/07 08:34:54 havasi Exp $ * */ @@ -67,12 +67,18 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #ifndef CONFIG_JFFS2_FS_WRITEBUFFER #define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) + +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) (1) +#endif + #define jffs2_is_writebuffered(c) (0) #define jffs2_cleanmarker_oob(c) (0) #define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) -#define jffs2_flash_write(c, ofs, len, retlen, buf) ((c)->mtd->write((c)->mtd, ofs, len, retlen, buf)) +#define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf) #define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) #define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) #define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) @@ -97,9 +103,15 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_is_writebuffered(c) (c->wbuf != NULL) #define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size ) + +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) \ ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \ c->mtd->type == MTD_RAM) +#endif + #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) @@ -192,7 +204,8 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c); /* writev.c */ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - +int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf); #endif /* __JFFS2_OS_LINUX_H__ */ diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index fcd6314cf179..4e60ba8da197 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.121 2005/07/20 15:32:28 dedekind Exp $ + * $Id: scan.c,v 1.122 2005/09/07 08:34:54 havasi Exp $ * */ #include @@ -18,22 +18,11 @@ #include #include #include "nodelist.h" +#include "summary.h" +#include "debug.h" #define DEFAULT_EMPTY_SCAN_SIZE 1024 -#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->dirty_size += _x; \ - jeb->free_size -= _x ; jeb->dirty_size += _x; \ - }while(0) -#define USED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->used_size += _x; \ - jeb->free_size -= _x ; jeb->used_size += _x; \ - }while(0) -#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->unchecked_size += _x; \ - jeb->free_size -= _x ; jeb->unchecked_size += _x; \ - }while(0) - #define noisy_printk(noise, args...) do { \ if (*(noise)) { \ printk(KERN_NOTICE args); \ @@ -47,23 +36,16 @@ static uint32_t pseudo_random; static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size); + unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s); /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs); + struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s); static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs); - -#define BLK_STATE_ALLFF 0 -#define BLK_STATE_CLEAN 1 -#define BLK_STATE_PARTDIRTY 2 -#define BLK_STATE_CLEANMARKER 3 -#define BLK_STATE_ALLDIRTY 4 -#define BLK_STATE_BADBLOCK 5 + struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s); static inline int min_free(struct jffs2_sb_info *c) { @@ -89,6 +71,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) uint32_t empty_blocks = 0, bad_blocks = 0; unsigned char *flashbuf = NULL; uint32_t buf_size = 0; + struct jffs2_summary *s = NULL; /* summary info collected by the scan process */ #ifndef __ECOS size_t pointlen; @@ -122,10 +105,23 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) return -ENOMEM; } + if (jffs2_sum_active()) { + s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + if (!s) { + JFFS2_WARNING("Can't allocate memory for summary\n"); + return -ENOMEM; + } + memset(s, 0, sizeof(struct jffs2_summary)); + } + for (i=0; inr_blocks; i++) { struct jffs2_eraseblock *jeb = &c->blocks[i]; - ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); + /* reset summary info for next eraseblock scan */ + jffs2_sum_reset_collected(s); + + ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), + buf_size, s); if (ret < 0) goto out; @@ -162,18 +158,18 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) break; case BLK_STATE_CLEAN: - /* Full (or almost full) of clean data. Clean list */ - list_add(&jeb->list, &c->clean_list); + /* Full (or almost full) of clean data. Clean list */ + list_add(&jeb->list, &c->clean_list); break; case BLK_STATE_PARTDIRTY: - /* Some data, but not full. Dirty list. */ - /* We want to remember the block with most free space - and stick it in the 'nextblock' position to start writing to it. */ - if (jeb->free_size > min_free(c) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { - /* Better candidate for the next writes to go to */ - if (c->nextblock) { + /* Some data, but not full. Dirty list. */ + /* We want to remember the block with most free space + and stick it in the 'nextblock' position to start writing to it. */ + if (jeb->free_size > min_free(c) && + (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { + /* Better candidate for the next writes to go to */ + if (c->nextblock) { c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; c->free_size -= c->nextblock->free_size; @@ -184,9 +180,14 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } else { list_add(&c->nextblock->list, &c->dirty_list); } + /* deleting summary information of the old nextblock */ + jffs2_sum_reset_collected(c->summary); } - c->nextblock = jeb; - } else { + /* update collected summary infromation for the current nextblock */ + jffs2_sum_move_collected(c, s); + D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); + c->nextblock = jeb; + } else { jeb->dirty_size += jeb->free_size + jeb->wasted_size; c->dirty_size += jeb->free_size + jeb->wasted_size; c->free_size -= jeb->free_size; @@ -197,30 +198,33 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } else { list_add(&jeb->list, &c->dirty_list); } - } + } break; case BLK_STATE_ALLDIRTY: /* Nothing valid - not even a clean marker. Needs erasing. */ - /* For now we just put it on the erasing list. We'll start the erases later */ + /* For now we just put it on the erasing list. We'll start the erases later */ D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); + list_add(&jeb->list, &c->erase_pending_list); c->nr_erasing_blocks++; break; - + case BLK_STATE_BADBLOCK: D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad\n", jeb->offset)); - list_add(&jeb->list, &c->bad_list); + list_add(&jeb->list, &c->bad_list); c->bad_size += c->sector_size; c->free_size -= c->sector_size; bad_blocks++; break; default: printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); - BUG(); + BUG(); } } - + + if (jffs2_sum_active() && s) + kfree(s); + /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ if (c->nextblock && (c->nextblock->dirty_size)) { c->nextblock->wasted_size += c->nextblock->dirty_size; @@ -265,7 +269,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) return ret; } -static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, +int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf, uint32_t ofs, uint32_t len) { int ret; @@ -286,14 +290,36 @@ static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, return 0; } +int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +{ + if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size + && (!jeb->first_node || !jeb->first_node->next_phys) ) + return BLK_STATE_CLEANMARKER; + + /* move blocks with max 4 byte dirty space to cleanlist */ + else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { + c->dirty_size -= jeb->dirty_size; + c->wasted_size += jeb->dirty_size; + jeb->wasted_size += jeb->dirty_size; + jeb->dirty_size = 0; + return BLK_STATE_CLEAN; + } else if (jeb->used_size || jeb->unchecked_size) + return BLK_STATE_PARTDIRTY; + else + return BLK_STATE_ALLDIRTY; +} + static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size) { + unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { struct jffs2_unknown_node *node; struct jffs2_unknown_node crcnode; + struct jffs2_sum_marker *sm; uint32_t ofs, prevofs; uint32_t hdr_crc, buf_ofs, buf_len; int err; int noise = 0; + + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER int cleanmarkerfound = 0; #endif @@ -319,10 +345,46 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo } } #endif + + if (jffs2_sum_active()) { + sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); + if (!sm) { + return -ENOMEM; + } + + err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - + sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); + if (err) { + kfree(sm); + return err; + } + + if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { + err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); + if (err) { + kfree(sm); + return err; + } + } + + kfree(sm); + + ofs = jeb->offset; + prevofs = jeb->offset - 1; + } + buf_ofs = jeb->offset; if (!buf_size) { buf_len = c->sector_size; + + if (jffs2_sum_active()) { + /* must reread because of summary test */ + err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); + if (err) + return err; + } + } else { buf_len = EMPTY_SCAN_SIZE(c->sector_size); err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); @@ -367,6 +429,8 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo noise = 10; + JFFS2_DBG_SUMMARY("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); + scan_more: while(ofs < jeb->offset + c->sector_size) { @@ -532,7 +596,7 @@ scan_more: buf_ofs = ofs; node = (void *)buf; } - err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); + err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs, s); if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -548,7 +612,7 @@ scan_more: buf_ofs = ofs; node = (void *)buf; } - err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); + err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs, s); if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -582,6 +646,8 @@ scan_more: break; case JFFS2_NODETYPE_PADDING: + if (jffs2_sum_active()) + jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -616,6 +682,13 @@ scan_more: } } + if (jffs2_sum_active()) { + if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) { + JFFS2_DBG_SUMMARY("There is not enough space for " + "summary information, disabling for this jeb!\n"); + jffs2_sum_disable_collecting(s); + } + } D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); @@ -628,24 +701,10 @@ scan_more: jeb->wasted_size = 0; } - if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size - && (!jeb->first_node || !jeb->first_node->next_phys) ) - return BLK_STATE_CLEANMARKER; - - /* move blocks with max 4 byte dirty space to cleanlist */ - else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { - c->dirty_size -= jeb->dirty_size; - c->wasted_size += jeb->dirty_size; - jeb->wasted_size += jeb->dirty_size; - jeb->dirty_size = 0; - return BLK_STATE_CLEAN; - } else if (jeb->used_size || jeb->unchecked_size) - return BLK_STATE_PARTDIRTY; - else - return BLK_STATE_ALLDIRTY; + return jffs2_scan_classify_jeb(c, jeb); } -static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) +struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ic; @@ -672,7 +731,7 @@ static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info } static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs) + struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; @@ -739,11 +798,16 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc pseudo_random += je32_to_cpu(ri->version); UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); + + if (jffs2_sum_active()) { + jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); + } + return 0; } static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs) + struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; @@ -817,6 +881,10 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo USED_SPACE(PAD(je32_to_cpu(rd->totlen))); jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + if (jffs2_sum_active()) { + jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset); + } + return 0; } diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c new file mode 100644 index 000000000000..cb5dd8f11e73 --- /dev/null +++ b/fs/jffs2/summary.c @@ -0,0 +1,729 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: summary.c,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "nodelist.h" +#include "debug.h" + +int jffs2_sum_init(struct jffs2_sb_info *c) +{ + c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + + if (!c->summary) { + JFFS2_WARNING("Can't allocate memory for summary information!\n"); + return -ENOMEM; + } + + memset(c->summary, 0, sizeof(struct jffs2_summary)); + + c->summary->sum_buf = vmalloc(c->sector_size); + + if (!c->summary->sum_buf) { + JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); + return -ENOMEM; + } + + JFFS2_DBG_SUMMARY("returned succesfully\n"); + + return 0; +} + +void jffs2_sum_exit(struct jffs2_sb_info *c) +{ + JFFS2_DBG_SUMMARY("called\n"); + + jffs2_sum_disable_collecting(c->summary); + + vfree(c->summary->sum_buf); + c->summary->sum_buf = NULL; + + kfree(c->summary); + c->summary = NULL; +} + +static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) +{ + if (!s->sum_list_head) + s->sum_list_head = (union jffs2_sum_mem *) item; + if (s->sum_list_tail) + s->sum_list_tail->u.next = (union jffs2_sum_mem *) item; + s->sum_list_tail = (union jffs2_sum_mem *) item; + + switch (je16_to_cpu(item->u.nodetype)) { + case JFFS2_NODETYPE_INODE: + s->sum_size += JFFS2_SUMMARY_INODE_SIZE; + s->sum_num++; + JFFS2_DBG_SUMMARY("inode (%u) added to summary\n", + je32_to_cpu(item->i.inode)); + break; + case JFFS2_NODETYPE_DIRENT: + s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); + s->sum_num++; + JFFS2_DBG_SUMMARY("dirent (%u) added to summary\n", + je32_to_cpu(item->d.ino)); + break; + default: + JFFS2_WARNING("UNKNOWN node type %u\n", + je16_to_cpu(item->u.nodetype)); + return 1; + } + return 0; +} + + +/* The following 3 functions are called from scan.c to collect summary info for not closed jeb */ + +int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size) +{ + JFFS2_DBG_SUMMARY("called with %u\n", size); + s->sum_padded += size; + return 0; +} + +int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, + uint32_t ofs) +{ + struct jffs2_sum_inode_mem *temp = kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL); + + if (!temp) + return -ENOMEM; + + temp->nodetype = ri->nodetype; + temp->inode = ri->ino; + temp->version = ri->version; + temp->offset = cpu_to_je32(ofs); /* relative offset from the begining of the jeb */ + temp->totlen = ri->totlen; + temp->next = NULL; + + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +} + +int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, + uint32_t ofs) +{ + struct jffs2_sum_dirent_mem *temp = + kmalloc(sizeof(struct jffs2_sum_dirent_mem) + rd->nsize, GFP_KERNEL); + + if (!temp) + return -ENOMEM; + + temp->nodetype = rd->nodetype; + temp->totlen = rd->totlen; + temp->offset = cpu_to_je32(ofs); /* relative from the begining of the jeb */ + temp->pino = rd->pino; + temp->version = rd->version; + temp->ino = rd->ino; + temp->nsize = rd->nsize; + temp->type = rd->type; + temp->next = NULL; + + memcpy(temp->name, rd->name, rd->nsize); + + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +} + +/* Cleanup every collected summary information */ + +static void jffs2_sum_clean_collected(struct jffs2_summary *s) +{ + union jffs2_sum_mem *temp; + + if (!s->sum_list_head) { + JFFS2_DBG_SUMMARY("already empty\n"); + } + while (s->sum_list_head) { + temp = s->sum_list_head; + s->sum_list_head = s->sum_list_head->u.next; + kfree(temp); + } + s->sum_list_tail = NULL; + s->sum_padded = 0; + s->sum_num = 0; +} + +void jffs2_sum_reset_collected(struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("called\n"); + jffs2_sum_clean_collected(s); + s->sum_size = 0; +} + +void jffs2_sum_disable_collecting(struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("called\n"); + jffs2_sum_clean_collected(s); + s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; +} + +int jffs2_sum_is_disabled(struct jffs2_summary *s) +{ + return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE); +} + +/* Move the collected summary information into sb (called from scan.c) */ + +void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", + c->summary->sum_size, c->summary->sum_num, + s->sum_size, s->sum_num); + + c->summary->sum_size = s->sum_size; + c->summary->sum_num = s->sum_num; + c->summary->sum_padded = s->sum_padded; + c->summary->sum_list_head = s->sum_list_head; + c->summary->sum_list_tail = s->sum_list_tail; + + s->sum_list_head = s->sum_list_tail = NULL; +} + +/* Called from wbuf.c to collect writed node info */ + +int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, + unsigned long count, uint32_t ofs) +{ + union jffs2_node_union *node; + struct jffs2_eraseblock *jeb; + + node = invecs[0].iov_base; + jeb = &c->blocks[ofs / c->sector_size]; + ofs -= jeb->offset; + + switch (je16_to_cpu(node->u.nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_mem *temp = + kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL); + + if (!temp) + goto no_mem; + + temp->nodetype = node->i.nodetype; + temp->inode = node->i.ino; + temp->version = node->i.version; + temp->offset = cpu_to_je32(ofs); + temp->totlen = node->i.totlen; + temp->next = NULL; + + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_mem *temp = + kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL); + + if (!temp) + goto no_mem; + + temp->nodetype = node->d.nodetype; + temp->totlen = node->d.totlen; + temp->offset = cpu_to_je32(ofs); + temp->pino = node->d.pino; + temp->version = node->d.version; + temp->ino = node->d.ino; + temp->nsize = node->d.nsize; + temp->type = node->d.type; + temp->next = NULL; + + switch (count) { + case 1: + memcpy(temp->name,node->d.name,node->d.nsize); + break; + + case 2: + memcpy(temp->name,invecs[1].iov_base,node->d.nsize); + break; + + default: + BUG(); /* impossible count value */ + break; + } + + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); + } + + case JFFS2_NODETYPE_PADDING: + JFFS2_DBG_SUMMARY("node PADDING\n"); + c->summary->sum_padded += je32_to_cpu(node->u.totlen); + break; + + case JFFS2_NODETYPE_CLEANMARKER: + JFFS2_DBG_SUMMARY("node CLEANMARKER\n"); + break; + + case JFFS2_NODETYPE_SUMMARY: + JFFS2_DBG_SUMMARY("node SUMMARY\n"); + break; + + default: + /* If you implement a new node type you should also implement + summary support for it or disable summary. + */ + BUG(); + break; + } + + return 0; + +no_mem: + JFFS2_WARNING("MEMORY ALLOCATION ERROR!"); + return -ENOMEM; +} + + +/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ + +static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_summary_node *summary, uint32_t *pseudo_random) +{ + struct jffs2_raw_node_ref *raw; + struct jffs2_inode_cache *ic; + struct jffs2_full_dirent *fd; + void *sp; + int i, ino; + + sp = summary->sum; + + for (i=0; isum_num); i++) { + JFFS2_DBG_SUMMARY("processing summary index %d\n", i); + + switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_flash *spi; + spi = sp; + + ino = je32_to_cpu(spi->inode); + + JFFS2_DBG_SUMMARY("Inode at 0x%08x\n", + jeb->offset + je32_to_cpu(spi->offset)); + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) { + JFFS2_NOTICE("allocation of node reference failed\n"); + kfree(summary); + return -ENOMEM; + } + + ic = jffs2_scan_make_ino_cache(c, ino); + if (!ic) { + JFFS2_NOTICE("scan_make_ino_cache failed\n"); + jffs2_free_raw_node_ref(raw); + kfree(summary); + return -ENOMEM; + } + + raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; + raw->__totlen = PAD(je32_to_cpu(spi->totlen)); + raw->next_phys = NULL; + raw->next_in_ino = ic->nodes; + + ic->nodes = raw; + if (!jeb->first_node) + jeb->first_node = raw; + if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; + *pseudo_random += je32_to_cpu(spi->version); + + UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); + + sp += JFFS2_SUMMARY_INODE_SIZE; + + break; + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_flash *spd; + spd = sp; + + JFFS2_DBG_SUMMARY("Dirent at 0x%08x\n", + jeb->offset + je32_to_cpu(spd->offset)); + + fd = jffs2_alloc_full_dirent(spd->nsize+1); + if (!fd) { + kfree(summary); + return -ENOMEM; + } + + memcpy(&fd->name, spd->name, spd->nsize); + fd->name[spd->nsize] = 0; + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) { + jffs2_free_full_dirent(fd); + JFFS2_NOTICE("allocation of node reference failed\n"); + kfree(summary); + return -ENOMEM; + } + + ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); + if (!ic) { + jffs2_free_full_dirent(fd); + jffs2_free_raw_node_ref(raw); + kfree(summary); + return -ENOMEM; + } + + raw->__totlen = PAD(je32_to_cpu(spd->totlen)); + raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE; + raw->next_phys = NULL; + raw->next_in_ino = ic->nodes; + ic->nodes = raw; + if (!jeb->first_node) + jeb->first_node = raw; + if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; + + fd->raw = raw; + fd->next = NULL; + fd->version = je32_to_cpu(spd->version); + fd->ino = je32_to_cpu(spd->ino); + fd->nhash = full_name_hash(fd->name, spd->nsize); + fd->type = spd->type; + USED_SPACE(PAD(je32_to_cpu(spd->totlen))); + jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + + *pseudo_random += je32_to_cpu(spd->version); + + sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize); + + break; + } + + default : { + JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); + kfree(summary); + return -EIO; + } + } + } + + kfree(summary); + return 0; +} + +/* Process the summary node - called from jffs2_scan_eraseblock() */ + +int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t *pseudo_random) +{ + struct jffs2_unknown_node crcnode; + struct jffs2_raw_node_ref *cache_ref; + struct jffs2_summary_node *summary; + int ret, sumsize; + uint32_t crc; + + sumsize = c->sector_size - ofs; + ofs += jeb->offset; + + JFFS2_DBG_SUMMARY("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", + jeb->offset, ofs, sumsize); + + summary = kmalloc(sumsize, GFP_KERNEL); + + if (!summary) { + return -ENOMEM; + } + + ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize); + + if (ret) { + kfree(summary); + return ret; + } + + /* OK, now check for node validity and CRC */ + crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); + crcnode.totlen = summary->totlen; + crc = crc32(0, &crcnode, sizeof(crcnode)-4); + + if (je32_to_cpu(summary->hdr_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node header is corrupt (bad CRC or " + "no summary at all)\n"); + goto crc_err; + } + + if (je32_to_cpu(summary->totlen) != sumsize) { + JFFS2_DBG_SUMMARY("Summary node is corrupt (wrong erasesize?)\n"); + goto crc_err; + } + + crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); + + if (je32_to_cpu(summary->node_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node is corrupt (bad CRC)\n"); + goto crc_err; + } + + crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); + + if (je32_to_cpu(summary->sum_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node data is corrupt (bad CRC)\n"); + goto crc_err; + } + + if ( je32_to_cpu(summary->cln_mkr) ) { + + JFFS2_DBG_SUMMARY("Summary : CLEANMARKER node \n"); + + if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { + JFFS2_DBG_SUMMARY("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", + je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); + UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); + } else if (jeb->first_node) { + JFFS2_DBG_SUMMARY("CLEANMARKER node not first node in block " + "(0x%08x)\n", jeb->offset); + UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); + } else { + struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); + + if (!marker_ref) { + JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); + kfree(summary); + return -ENOMEM; + } + + marker_ref->next_in_ino = NULL; + marker_ref->next_phys = NULL; + marker_ref->flash_offset = jeb->offset | REF_NORMAL; + marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); + jeb->first_node = jeb->last_node = marker_ref; + + USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); + } + } + + if (je32_to_cpu(summary->padded)) { + DIRTY_SPACE(je32_to_cpu(summary->padded)); + } + + ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); + if (ret) + return ret; + + /* for PARANOIA_CHECK */ + cache_ref = jffs2_alloc_raw_node_ref(); + + if (!cache_ref) { + JFFS2_NOTICE("Failed to allocate node ref for cache\n"); + return -ENOMEM; + } + + cache_ref->next_in_ino = NULL; + cache_ref->next_phys = NULL; + cache_ref->flash_offset = ofs | REF_NORMAL; + cache_ref->__totlen = sumsize; + + if (!jeb->first_node) + jeb->first_node = cache_ref; + if (jeb->last_node) + jeb->last_node->next_phys = cache_ref; + jeb->last_node = cache_ref; + + USED_SPACE(sumsize); + + jeb->wasted_size += jeb->free_size; + c->wasted_size += jeb->free_size; + c->free_size -= jeb->free_size; + jeb->free_size = 0; + + return jffs2_scan_classify_jeb(c, jeb); + +crc_err: + JFFS2_WARNING("Summary node crc error, skipping summary information.\n"); + + return 0; +} + +/* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ + +static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t infosize, uint32_t datasize, int padsize) +{ + struct jffs2_summary_node isum; + union jffs2_sum_mem *temp; + struct jffs2_sum_marker *sm; + struct kvec vecs[2]; + void *wpage; + int ret; + size_t retlen; + + memset(c->summary->sum_buf, 0xff, datasize); + memset(&isum, 0, sizeof(isum)); + + isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); + isum.totlen = cpu_to_je32(infosize); + isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4)); + isum.padded = cpu_to_je32(c->summary->sum_padded); + isum.cln_mkr = cpu_to_je32(c->cleanmarker_size); + isum.sum_num = cpu_to_je32(c->summary->sum_num); + wpage = c->summary->sum_buf; + + while (c->summary->sum_num) { + + switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_flash *sino_ptr = wpage; + + sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype; + sino_ptr->inode = c->summary->sum_list_head->i.inode; + sino_ptr->version = c->summary->sum_list_head->i.version; + sino_ptr->offset = c->summary->sum_list_head->i.offset; + sino_ptr->totlen = c->summary->sum_list_head->i.totlen; + + wpage += JFFS2_SUMMARY_INODE_SIZE; + + break; + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; + + sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype; + sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen; + sdrnt_ptr->offset = c->summary->sum_list_head->d.offset; + sdrnt_ptr->pino = c->summary->sum_list_head->d.pino; + sdrnt_ptr->version = c->summary->sum_list_head->d.version; + sdrnt_ptr->ino = c->summary->sum_list_head->d.ino; + sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; + sdrnt_ptr->type = c->summary->sum_list_head->d.type; + + memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, + c->summary->sum_list_head->d.nsize); + + wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); + + break; + } + + default : { + BUG(); /* unknown node in summary information */ + } + } + + temp = c->summary->sum_list_head; + c->summary->sum_list_head = c->summary->sum_list_head->u.next; + kfree(temp); + + c->summary->sum_num--; + } + + jffs2_sum_reset_collected(c->summary); + + wpage += padsize; + + sm = wpage; + sm->offset = cpu_to_je32(c->sector_size - jeb->free_size); + sm->magic = cpu_to_je32(JFFS2_SUM_MAGIC); + + isum.sum_crc = cpu_to_je32(crc32(0, c->summary->sum_buf, datasize)); + isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8)); + + vecs[0].iov_base = &isum; + vecs[0].iov_len = sizeof(isum); + vecs[1].iov_base = c->summary->sum_buf; + vecs[1].iov_len = datasize; + + JFFS2_DBG_SUMMARY("JFFS2: writing out data to flash to pos : 0x%08x\n", + jeb->offset + c->sector_size - jeb->free_size); + + spin_unlock(&c->erase_completion_lock); + ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - + jeb->free_size, &retlen, 0); + spin_lock(&c->erase_completion_lock); + + + if (ret || (retlen != infosize)) { + JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); + + c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; + WASTED_SPACE(infosize); + + return 1; + } + + return 0; +} + +/* Write out summary information - called from jffs2_do_reserve_space */ + +int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) +{ + struct jffs2_raw_node_ref *summary_ref; + int datasize, infosize, padsize, ret; + struct jffs2_eraseblock *jeb; + + JFFS2_DBG_SUMMARY("called\n"); + + jeb = c->nextblock; + + if (!c->summary->sum_num || !c->summary->sum_list_head) { + JFFS2_WARNING("Empty summary info!!!\n"); + BUG(); + } + + datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); + infosize = sizeof(struct jffs2_summary_node) + datasize; + padsize = jeb->free_size - infosize; + infosize += padsize; + datasize += padsize; + + /* Is there enough space for summary? */ + if (padsize < 0) { + /* don't try to write out summary for this jeb */ + jffs2_sum_disable_collecting(c->summary); + + JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); + return 0; + } + + ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); + if (ret) + return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ + + /* for ACCT_PARANOIA_CHECK */ + spin_unlock(&c->erase_completion_lock); + summary_ref = jffs2_alloc_raw_node_ref(); + spin_lock(&c->erase_completion_lock); + + if (!summary_ref) { + JFFS2_NOTICE("Failed to allocate node ref for summary\n"); + return -ENOMEM; + } + + summary_ref->next_in_ino = NULL; + summary_ref->next_phys = NULL; + summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; + summary_ref->__totlen = infosize; + + if (!jeb->first_node) + jeb->first_node = summary_ref; + if (jeb->last_node) + jeb->last_node->next_phys = summary_ref; + jeb->last_node = summary_ref; + + USED_SPACE(infosize); + + return 0; +} diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h new file mode 100644 index 000000000000..e6b0a69acbd4 --- /dev/null +++ b/fs/jffs2/summary.h @@ -0,0 +1,183 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: summary.h,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * + */ + +#ifndef JFFS2_SUMMARY_H +#define JFFS2_SUMMARY_H + +#include +#include + +#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->dirty_size += _x; \ + jeb->free_size -= _x ; jeb->dirty_size += _x; \ + }while(0) +#define USED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->used_size += _x; \ + jeb->free_size -= _x ; jeb->used_size += _x; \ + }while(0) +#define WASTED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->wasted_size += _x; \ + jeb->free_size -= _x ; jeb->wasted_size += _x; \ + }while(0) +#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->unchecked_size += _x; \ + jeb->free_size -= _x ; jeb->unchecked_size += _x; \ + }while(0) + +#define BLK_STATE_ALLFF 0 +#define BLK_STATE_CLEAN 1 +#define BLK_STATE_PARTDIRTY 2 +#define BLK_STATE_CLEANMARKER 3 +#define BLK_STATE_ALLDIRTY 4 +#define BLK_STATE_BADBLOCK 5 + +#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff +#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) +#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) + +/* Summary structures used on flash */ + +struct jffs2_sum_unknown_flash +{ + jint16_t nodetype; /* node type */ +}; + +struct jffs2_sum_inode_flash +{ + jint16_t nodetype; /* node type */ + jint32_t inode; /* inode number */ + jint32_t version; /* inode version */ + jint32_t offset; /* offset on jeb */ + jint32_t totlen; /* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_flash +{ + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; /* record length */ + jint32_t offset; /* offset on jeb */ + jint32_t pino; /* parent inode */ + jint32_t version; /* dirent version */ + jint32_t ino; /* == zero for unlink */ + uint8_t nsize; /* dirent name size */ + uint8_t type; /* dirent type */ + uint8_t name[0]; /* dirent name */ +} __attribute__((packed)); + +union jffs2_sum_flash +{ + struct jffs2_sum_unknown_flash u; + struct jffs2_sum_inode_flash i; + struct jffs2_sum_dirent_flash d; +}; + +/* Summary structures used in the memory */ + +struct jffs2_sum_unknown_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* node type */ +}; + +struct jffs2_sum_inode_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* node type */ + jint32_t inode; /* inode number */ + jint32_t version; /* inode version */ + jint32_t offset; /* offset on jeb */ + jint32_t totlen; /* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; /* record length */ + jint32_t offset; /* ofset on jeb */ + jint32_t pino; /* parent inode */ + jint32_t version; /* dirent version */ + jint32_t ino; /* == zero for unlink */ + uint8_t nsize; /* dirent name size */ + uint8_t type; /* dirent type */ + uint8_t name[0]; /* dirent name */ +} __attribute__((packed)); + +union jffs2_sum_mem +{ + struct jffs2_sum_unknown_mem u; + struct jffs2_sum_inode_mem i; + struct jffs2_sum_dirent_mem d; +}; + +/* Summary related information stored in superblock */ + +struct jffs2_summary +{ + uint32_t sum_size; /* collected summary information for nextblock */ + uint32_t sum_num; + uint32_t sum_padded; + union jffs2_sum_mem *sum_list_head; + union jffs2_sum_mem *sum_list_tail; + + jint32_t *sum_buf; /* buffer for writing out summary */ +}; + +/* Summary marker is stored at the end of every sumarized erase block */ + +struct jffs2_sum_marker +{ + jint32_t offset; /* offset of the summary node in the jeb */ + jint32_t magic; /* == JFFS2_SUM_MAGIC */ +}; + +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_summary_node) + sizeof(struct jffs2_sum_marker)) + +#ifdef CONFIG_JFFS2_SUMMARY /* SUMMARY SUPPORT ENABLED */ + +#define jffs2_sum_active() (1) +int jffs2_sum_init(struct jffs2_sb_info *c); +void jffs2_sum_exit(struct jffs2_sb_info *c); +void jffs2_sum_disable_collecting(struct jffs2_summary *s); +int jffs2_sum_is_disabled(struct jffs2_summary *s); +void jffs2_sum_reset_collected(struct jffs2_summary *s); +void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s); +int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, + unsigned long count, uint32_t to); +int jffs2_sum_write_sumnode(struct jffs2_sb_info *c); +int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); +int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); +int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); +int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t *pseudo_random); + +#else /* SUMMARY DISABLED */ + +#define jffs2_sum_active() (0) +#define jffs2_sum_init(a) (0) +#define jffs2_sum_exit(a) +#define jffs2_sum_disable_collecting(a) +#define jffs2_sum_is_disabled(a) (0) +#define jffs2_sum_reset_collected(a) +#define jffs2_sum_add_kvec(a,b,c,d) (0) +#define jffs2_sum_move_collected(a,b) +#define jffs2_sum_write_sumnode(a) (0) +#define jffs2_sum_add_padding_mem(a,b) +#define jffs2_sum_add_inode_mem(a,b,c) +#define jffs2_sum_add_dirent_mem(a,b,c) +#define jffs2_sum_scan_sumnode(a,b,c,d) (0) + +#endif /* CONFIG_JFFS2_SUMMARY */ + +#endif /* JFFS2_SUMMARY_H */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 58496a03a1d2..99028af3f69e 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.108 2005/08/31 13:51:00 havasi Exp $ + * $Id: super.c,v 1.109 2005/09/07 08:34:55 havasi Exp $ * */ @@ -282,6 +282,9 @@ static void jffs2_put_super (struct super_block *sb) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); up(&c->alloc_sem); + + jffs2_sum_exit(c); + jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); if (jffs2_blocks_use_vmalloc(c)) @@ -320,6 +323,9 @@ static int __init init_jffs2_fs(void) printk(KERN_INFO "JFFS2 version 2.2." #ifdef CONFIG_JFFS2_FS_WRITEBUFFER " (NAND)" +#endif +#ifdef CONFIG_JFFS2_SUMMARY + " (SUMMARY) " #endif " (C) 2001-2003 Red Hat, Inc.\n"); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 8c06d3a2b17d..86860dbc670c 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.97 2005/08/06 04:51:30 nico Exp $ + * $Id: wbuf.c,v 1.98 2005/09/07 08:34:55 havasi Exp $ * */ @@ -265,7 +265,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* ... and get an allocation of space from a shiny new block instead */ - ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); + ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); if (ret) { printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); kfree(buf); @@ -836,6 +836,12 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig alldone: *retlen = donelen; + if (jffs2_sum_active()) { + int res = jffs2_sum_add_kvec(c, invecs, count, (uint32_t) to); + if (res) + return res; + } + if (c->wbuf_len && ino) jffs2_wbuf_dirties_inode(c, ino); @@ -855,7 +861,7 @@ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *r struct kvec vecs[1]; if (!jffs2_is_writebuffered(c)) - return c->mtd->write(c->mtd, ofs, len, retlen, buf); + return jffs2_flash_direct_write(c, ofs, len, retlen, buf); vecs[0].iov_base = (unsigned char *) buf; vecs[0].iov_len = len; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 0a194759bbbd..ea411518d801 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $ + * $Id: write.c,v 1.96 2005/09/07 08:34:55 havasi Exp $ * */ @@ -153,13 +153,15 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, + &dummy, JFFS2_SUMMARY_INODE_SIZE); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, + &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); } @@ -299,13 +301,15 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, + &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, + &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); } @@ -362,7 +366,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, retry: D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); - ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); break; @@ -449,7 +454,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str /* Try to reserve enough space for both node and dirent. * Just the node will do for now, though */ - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); if (ret) { up(&f->sem); @@ -478,7 +484,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ @@ -549,7 +556,8 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); return ret; @@ -658,7 +666,8 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); return ret; diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index f079f8388566..6d8c27c5e723 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.6 2004/11/16 20:36:12 dwmw2 Exp $ + * $Id: writev.c,v 1.7 2005/09/07 08:34:55 havasi Exp $ * */ @@ -44,7 +44,37 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, { if (c->mtd->writev) return c->mtd->writev(c->mtd, vecs, count, to, retlen); - else + else { + if (jffs2_sum_active()) { + int res; + + res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to); + if (res) { + return res; + } + } + return mtd_fake_writev(c->mtd, vecs, count, to, retlen); + } } +int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf) +{ + int ret; + ret = c->mtd->write(c->mtd, ofs, len, retlen, buf); + + if (jffs2_sum_active()) { + struct kvec vecs[1]; + int res; + + vecs[0].iov_base = (unsigned char *) buf; + vecs[0].iov_len = len; + + res = jffs2_sum_add_kvec(c, vecs, 1, (uint32_t) ofs); + if (res) { + return res; + } + } + return ret; +} diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index a66d0a8b70e4..acb51a3669a2 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ + * $Id: jffs2.h,v 1.37 2005/09/07 08:34:55 havasi Exp $ * */ @@ -28,6 +28,9 @@ #define JFFS2_EMPTY_BITMASK 0xffff #define JFFS2_DIRTY_BITMASK 0x0000 +/* Summary node MAGIC marker */ +#define JFFS2_SUM_MAGIC 0x02851885 + /* We only allow a single char for length, and 0xFF is empty flash so we don't want it confused with a real length. Hence max 254. */ @@ -60,6 +63,8 @@ #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) #define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) +#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) + // Maybe later... //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) @@ -146,10 +151,24 @@ struct jffs2_raw_inode uint8_t data[0]; } __attribute__((packed)); +struct jffs2_summary_node{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_INODE_SUM */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t sum_num; /* number of sum entries*/ + jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */ + jint32_t padded; /* sum of the size of padding nodes */ + jint32_t sum_crc; /* summary information crc */ + jint32_t node_crc; /* node crc */ + jint32_t sum[0]; /* inode summary info */ +} __attribute__((packed)); + union jffs2_node_union { struct jffs2_raw_inode i; struct jffs2_raw_dirent d; struct jffs2_unknown_node u; + struct jffs2_summary_node s; }; #endif /* __LINUX_JFFS2_H__ */ diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 1e21546622de..5087612ed9ac 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.52 2005/05/19 16:12:17 gleixner Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.53 2005/09/07 08:34:56 havasi Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -112,6 +112,8 @@ struct jffs2_sb_info { uint32_t fsdata_len; #endif + struct jffs2_summary *summary; /* Summary information */ + /* OS-private pointer for getting back to master superblock info */ void *os_priv; }; -- cgit v1.2.3 From 962034f43937d02a1c18e802a6641aed0a266ac5 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 15 Sep 2005 14:58:53 +0100 Subject: [MTD] NAND: Add suspend/resume functionality The changes introduced allow to suspend/resume NAND flash. A new state (FL_PM_SUSPENDED) is introduced, as well as routines for mtd->suspend and mtd->resume to put the flash in suspended state from software pov. Signed-off-by: Vitaly Wool Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/nand_base.c | 46 ++++++++++++++++++++++++++++++++++++++------ include/linux/mtd/nand.h | 3 ++- 2 files changed, 42 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index cdf108619344..4e22317397e8 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -46,6 +46,8 @@ * perform extra error status checks on erase and write failures. This required * adding a wrapper function for nand_read_ecc. * + * 08-20-2005 vwool: suspend/resume added + * * Credits: * David Woodhouse for adding multichip support * @@ -59,7 +61,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.148 2005/08/04 17:14:48 gleixner Exp $ + * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool 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 @@ -153,7 +155,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int #define nand_verify_pages(...) (0) #endif -static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); +static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); /** * nand_release_device - [GENERIC] release chip @@ -756,7 +758,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, * * Get the device and lock it for exclusive access */ -static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) +static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) { struct nand_chip *active; spinlock_t *lock; @@ -779,7 +781,11 @@ retry: if (active == this && this->state == FL_READY) { this->state = new_state; spin_unlock(lock); - return; + return 0; + } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(wq, &wait); @@ -2284,6 +2290,34 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) return this->block_markbad(mtd, ofs); } +/** + * nand_suspend - [MTD Interface] Suspend the NAND flash + * @mtd: MTD device structure + */ +static int nand_suspend(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + return nand_get_device (this, mtd, FL_PM_SUSPENDED); +} + +/** + * nand_resume - [MTD Interface] Resume the NAND flash + * @mtd: MTD device structure + */ +static void nand_resume(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + nand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not " + "in suspended state\n"); + +} + + /** * nand_scan - [NAND Interface] Scan for the NAND device * @mtd: MTD device structure @@ -2643,8 +2677,8 @@ int nand_scan (struct mtd_info *mtd, int maxchips) mtd->sync = nand_sync; mtd->lock = NULL; mtd->unlock = NULL; - mtd->suspend = NULL; - mtd->resume = NULL; + mtd->suspend = nand_suspend; + mtd->resume = nand_resume; mtd->block_isbad = nand_block_isbad; mtd->block_markbad = nand_block_markbad; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 9b5b76217584..2d36413b2f94 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -5,7 +5,7 @@ * Steven J. Hill * Thomas Gleixner * - * $Id: nand.h,v 1.73 2005/05/31 19:39:17 gleixner Exp $ + * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool 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 @@ -244,6 +244,7 @@ typedef enum { FL_ERASING, FL_SYNCING, FL_CACHEDPRG, + FL_PM_SUSPENDED, } nand_state_t; /* Keep gcc happy */ -- cgit v1.2.3 From 733802d974e5af42acb7cd61b16c0ce6dd03b7ed Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Thu, 22 Sep 2005 12:25:00 +0100 Subject: [JFFS2] Debug code simplification, update TODO Simplify the debugging code further. Update the TODO list Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/TODO | 38 +++++++-------- fs/jffs2/build.c | 112 +++++++++++++++++++++----------------------- fs/jffs2/debug.c | 3 +- fs/jffs2/debug.h | 50 +++++++++++++------- fs/jffs2/erase.c | 2 +- fs/jffs2/malloc.c | 34 +++++++------- fs/jffs2/nodelist.c | 107 ++++++++++++++++++++++-------------------- fs/jffs2/nodemgmt.c | 6 +-- fs/jffs2/os-linux.h | 6 +-- fs/jffs2/readinode.c | 32 ++++++------- fs/jffs2/scan.c | 48 ++----------------- fs/jffs2/summary.c | 53 +++++++++++---------- fs/jffs2/wbuf.c | 5 +- include/linux/jffs2_fs_sb.h | 5 +- 14 files changed, 235 insertions(+), 266 deletions(-) (limited to 'include') diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO index 2bff82fd221f..d0e23b26fa50 100644 --- a/fs/jffs2/TODO +++ b/fs/jffs2/TODO @@ -1,5 +1,11 @@ -$Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ +$Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $ + - support asynchronous operation -- add a per-fs 'reserved_space' count, + let each outstanding write reserve the _maximum_ amount of physical + space it could take. Let GC flush the outstanding writes because the + reservations will necessarily be pessimistic. With this we could even + do shared writable mmap, if we can have a fs hook for do_wp_page() to + make the reservation. - disable compression in commit_write()? - fine-tune the allocation / GC thresholds - chattr support - turning on/off and tuning compression per-inode @@ -11,26 +17,15 @@ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - test, test, test - NAND flash support: - - flush_wbuf using GC to fill it, don't just pad. - - Deal with write errors. Data don't get lost - we just have to write - the affected node(s) out again somewhere else. - - make fsync flush only if actually required - - make sys_sync() work. - - reboot notifier - - timed flush of old wbuf - - fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead. - + - almost done :) + - use bad block check instead of the hardwired byte check - Optimisations: - - Stop GC from decompressing and immediately recompressing nodes which could - just be copied intact. (We now keep track of REF_PRISTINE flag. Easy now.) - - Furthermore, in the case where it could be copied intact we don't even need - to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag - to show a node can be copied intact and it's _not_ in icache, we could just do - it, fix up the next_in_ino list and move on. We would need a way to find out - _whether_ it's in icache though -- if it's in icache we also need to do the - fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could - help. (We have half of this now.) + - Split writes so they go to two separate blocks rather than just c->nextblock. + By writing _new_ nodes to one block, and garbage-collected REF_PRISTINE + nodes to a different one, we can separate clean nodes from those which + are likely to become dirty, and end up with blocks which are each far + closer to 100% or 0% clean, hence speeding up later GC progress dramatically. - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in the full dirent, we only need to go to the flash in lookup() when we think we've got a match, and in readdir(). @@ -38,3 +33,8 @@ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into jffs2_mark_node_obsolete(). Can all callers work it out? - Remove size from jffs2_raw_node_frag. + +dedekind: +1. __jffs2_flush_wbuf() has a strange 'pad' parameter. Eliminate. +2. get_sb()->build_fs()->scan() path... Why get_sb() removes scan()'s crap in + case of failure? scan() does not clean everything. Fix. diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index f2cf562ebd2a..ac393b3d6ea3 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.79 2005/09/07 11:21:57 havasi Exp $ + * $Id: build.c,v 1.83 2005/09/21 15:52:33 dedekind Exp $ * */ @@ -18,7 +18,8 @@ #include #include "nodelist.h" -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **); +static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, + struct jffs2_inode_cache *, struct jffs2_full_dirent **); static inline struct jffs2_inode_cache * first_inode_chain(int *i, struct jffs2_sb_info *c) @@ -46,11 +47,12 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) ic = next_inode(&i, ic, (c))) -static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, + struct jffs2_inode_cache *ic) { struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "jffs2_build_inode building directory inode #%u\n", ic->ino)); + dbg_fsbuild("building directory inode #%u\n", ic->ino); /* For each child, increase nlink */ for(fd = ic->scan_dents; fd; fd = fd->next) { @@ -58,26 +60,23 @@ static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2 if (!fd->ino) continue; - /* XXX: Can get high latency here with huge directories */ + /* we can get high latency here with huge directories */ child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { - printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", + dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", fd->name, fd->ino, ic->ino); jffs2_mark_node_obsolete(c, fd->raw); continue; } if (child_ic->nlink++ && fd->type == DT_DIR) { - printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); - if (fd->ino == 1 && ic->ino == 1) { - printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); - printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); - } - /* What do we do about it? */ + JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", + fd->name, fd->ino, ic->ino); + /* TODO: What do we do about it? */ } - D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); - /* Can't free them. We might need them in pass 2 */ + dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); + /* Can't free scan_dents so far. We might need them in pass 2 */ } } @@ -94,6 +93,8 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) struct jffs2_full_dirent *fd; struct jffs2_full_dirent *dead_fds = NULL; + dbg_fsbuild("build FS data structures\n"); + /* First, scan the medium and build all the inode caches with lists of physical nodes */ @@ -103,33 +104,29 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) if (ret) goto exit; - D1(printk(KERN_DEBUG "Scanned flash completely\n")); + dbg_fsbuild("scanned flash completely\n"); jffs2_dbg_dump_block_lists_nolock(c); + dbg_fsbuild("pass 1 starting\n"); c->flags |= JFFS2_SB_FLAG_BUILDING; /* Now scan the directory tree, increasing nlink according to every dirent found. */ for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); - - D1(BUG_ON(ic->ino > c->highest_ino)); - if (ic->scan_dents) { jffs2_build_inode_pass1(c, ic); cond_resched(); } } - D1(printk(KERN_DEBUG "Pass 1 complete\n")); + dbg_fsbuild("pass 1 complete\n"); /* Next, scan for inodes with nlink == 0 and remove them. If they were directories, then decrement the nlink of their children too, and repeat the scan. As that's going to be a fairly uncommon occurrence, it's not so evil to do it this way. Recursion bad. */ - D1(printk(KERN_DEBUG "Pass 2 starting\n")); + dbg_fsbuild("pass 2 starting\n"); for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes)); if (ic->nlink) continue; @@ -137,26 +134,24 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) cond_resched(); } - D1(printk(KERN_DEBUG "Pass 2a starting\n")); + dbg_fsbuild("pass 2a starting\n"); while (dead_fds) { fd = dead_fds; dead_fds = fd->next; ic = jffs2_get_ino_cache(c, fd->ino); - D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic)); if (ic) jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); jffs2_free_full_dirent(fd); } - D1(printk(KERN_DEBUG "Pass 2 complete\n")); + dbg_fsbuild("pass 2a complete\n"); + dbg_fsbuild("freeing temporary data structures\n"); /* Finally, we can scan again and free the dirent structs */ for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); - while(ic->scan_dents) { fd = ic->scan_dents; ic->scan_dents = fd->next; @@ -167,8 +162,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) } c->flags &= ~JFFS2_SB_FLAG_BUILDING; - D1(printk(KERN_DEBUG "Pass 3 complete\n")); - jffs2_dbg_dump_block_lists_nolock(c); + dbg_fsbuild("FS build complete\n"); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); @@ -189,24 +183,26 @@ exit: return ret; } -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds) +static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, + struct jffs2_inode_cache *ic, + struct jffs2_full_dirent **dead_fds) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); + dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino); raw = ic->nodes; while (raw != (void *)ic) { struct jffs2_raw_node_ref *next = raw->next_in_ino; - D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); + dbg_fsbuild("obsoleting node at 0x%08x\n", ref_offset(raw)); jffs2_mark_node_obsolete(c, raw); raw = next; } if (ic->scan_dents) { int whinged = 0; - D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); + dbg_fsbuild("inode #%u was a directory which may have children...\n", ic->ino); while(ic->scan_dents) { struct jffs2_inode_cache *child_ic; @@ -216,21 +212,19 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jf if (!fd->ino) { /* It's a deletion dirent. Ignore it */ - D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); + dbg_fsbuild("child \"%s\" is a deletion dirent, skipping...\n", fd->name); jffs2_free_full_dirent(fd); continue; } - if (!whinged) { + if (!whinged) whinged = 1; - printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - } - D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", - fd->name, fd->ino)); + dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino); child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { - printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); + dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n", + fd->name, fd->ino); jffs2_free_full_dirent(fd); continue; } @@ -241,13 +235,13 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jf child_ic->nlink--; if (!child_ic->nlink) { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n", - fd->ino, fd->name)); + dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", + fd->ino, fd->name); fd->next = *dead_fds; *dead_fds = fd; } else { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", - fd->ino, fd->name, child_ic->nlink)); + dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", + fd->ino, fd->name, child_ic->nlink); jffs2_free_full_dirent(fd); } } @@ -295,20 +289,20 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) trying to GC to make more space. It'll be a fruitless task */ c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); - D1(printk(KERN_DEBUG "JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", - c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks)); - D1(printk(KERN_DEBUG "Blocks required to allow deletion: %d (%d KiB)\n", - c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow writes: %d (%d KiB)\n", - c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to quiesce GC thread: %d (%d KiB)\n", - c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow GC merges: %d (%d KiB)\n", - c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to GC bad blocks: %d (%d KiB)\n", - c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Amount of dirty space required to GC: %d bytes\n", - c->nospc_dirty_size)); + dbg_fsbuild("JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", + c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks); + dbg_fsbuild("Blocks required to allow deletion: %d (%d KiB)\n", + c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024); + dbg_fsbuild("Blocks required to allow writes: %d (%d KiB)\n", + c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024); + dbg_fsbuild("Blocks required to quiesce GC thread: %d (%d KiB)\n", + c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024); + dbg_fsbuild("Blocks required to allow GC merges: %d (%d KiB)\n", + c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024); + dbg_fsbuild("Blocks required to GC bad blocks: %d (%d KiB)\n", + c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); + dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", + c->nospc_dirty_size); } int jffs2_do_mount_fs(struct jffs2_sb_info *c) @@ -358,7 +352,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) return ret; if (jffs2_build_filesystem(c)) { - D1(printk(KERN_DEBUG "build_fs failed\n")); + dbg_fsbuild("build_fs failed\n"); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); #ifndef __ECOS diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 28983501bcef..0947284f45dd 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.10 2005/09/14 16:57:32 dedekind Exp $ + * $Id: debug.c,v 1.11 2005/09/21 13:28:35 dedekind Exp $ * */ #include @@ -15,6 +15,7 @@ #include #include #include +#include #include "nodelist.h" #include "debug.h" diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 7328e67bebb6..da1417d38914 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.16 2005/09/14 16:57:32 dedekind Exp $ + * $Id: debug.h,v 1.18 2005/09/21 10:26:26 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -23,16 +23,23 @@ /* Enable "paranoia" checks and dumps */ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS + +/* + * By defining/undefining the below macros one may select debugging messages + * fro specific JFFS2 subsystems. + */ #define JFFS2_DBG_READINODE_MESSAGES #define JFFS2_DBG_FRAGTREE_MESSAGES #define JFFS2_DBG_DENTLIST_MESSAGES #define JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_INOCACHE_MESSAGES #define JFFS2_DBG_SUMMARY_MESSAGES +#define JFFS2_DBG_FSBUILD_MESSAGES #endif #if CONFIG_JFFS2_FS_DEBUG == 2 #define JFFS2_DBG_FRAGTREE2_MESSAGES +#define JFFS2_DBG_MEMALLOC_MESSAGES #endif /* Sanity checks are supposed to be light-weight and enabled by default */ @@ -40,7 +47,7 @@ /* * Dx() are mainly used for debugging messages, they must go away and be - * superseded by nicer JFFS2_DBG_XXX() macros... + * superseded by nicer dbg_xxx() macros... */ #if CONFIG_JFFS2_FS_DEBUG > 0 #define D1(x) x @@ -105,56 +112,63 @@ */ /* Read inode debugging messages */ #ifdef JFFS2_DBG_READINODE_MESSAGES -#define JFFS2_DBG_READINODE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_readinode(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_READINODE(fmt, ...) +#define dbg_readinode(fmt, ...) #endif /* Fragtree build debugging messages */ #ifdef JFFS2_DBG_FRAGTREE_MESSAGES -#define JFFS2_DBG_FRAGTREE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_fragtree(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_FRAGTREE(fmt, ...) +#define dbg_fragtree(fmt, ...) #endif #ifdef JFFS2_DBG_FRAGTREE2_MESSAGES -#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_fragtree2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_FRAGTREE2(fmt, ...) +#define dbg_fragtree2(fmt, ...) #endif /* Directory entry list manilulation debugging messages */ #ifdef JFFS2_DBG_DENTLIST_MESSAGES -#define JFFS2_DBG_DENTLIST(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_dentlist(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_DENTLIST(fmt, ...) +#define dbg_dentlist(fmt, ...) #endif /* Print the messages about manipulating node_refs */ #ifdef JFFS2_DBG_NODEREF_MESSAGES -#define JFFS2_DBG_NODEREF(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_noderef(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_NODEREF(fmt, ...) +#define dbg_noderef(fmt, ...) #endif /* Manipulations with the list of inodes (JFFS2 inocache) */ #ifdef JFFS2_DBG_INOCACHE_MESSAGES -#define JFFS2_DBG_INOCACHE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_inocache(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_INOCACHE(fmt, ...) +#define dbg_inocache(fmt, ...) #endif /* Summary debugging messages */ #ifdef JFFS2_DBG_SUMMARY_MESSAGES -#define JFFS2_DBG_SUMMARY(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_summary(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define dbg_summary(fmt, ...) +#endif + +/* File system build messages */ +#ifdef JFFS2_DBG_FSBUILD_MESSAGES +#define dbg_fsbuild(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_SUMMARY(fmt, ...) +#define dbg_fsbuild(fmt, ...) #endif /* Watch the object allocations */ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES -#define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_memalloc(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_MEMALLOC(fmt, ...) +#define dbg_memalloc(fmt, ...) #endif diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a8a0908142d9..347de4efeeeb 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.83 2005/07/22 10:32:08 dedekind Exp $ + * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $ * */ diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 734801145bf8..f27df015f3ec 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.29 2005/07/27 14:16:53 dedekind Exp $ + * $Id: malloc.c,v 1.30 2005/09/20 14:27:34 dedekind Exp $ * */ @@ -97,13 +97,13 @@ struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) { struct jffs2_full_dirent *ret; ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_full_dirent(struct jffs2_full_dirent *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kfree(x); } @@ -111,13 +111,13 @@ struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) { struct jffs2_full_dnode *ret; ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_full_dnode(struct jffs2_full_dnode *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(full_dnode_slab, x); } @@ -125,13 +125,13 @@ struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) { struct jffs2_raw_dirent *ret; ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_dirent_slab, x); } @@ -139,13 +139,13 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) { struct jffs2_raw_inode *ret; ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_inode(struct jffs2_raw_inode *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_inode_slab, x); } @@ -153,14 +153,14 @@ struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) { struct jffs2_tmp_dnode_info *ret; ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(tmp_dnode_info_slab, x); } @@ -168,13 +168,13 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) { struct jffs2_raw_node_ref *ret; ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_node_ref_slab, x); } @@ -182,13 +182,13 @@ struct jffs2_node_frag *jffs2_alloc_node_frag(void) { struct jffs2_node_frag *ret; ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_node_frag(struct jffs2_node_frag *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(node_frag_slab, x); } @@ -196,12 +196,12 @@ struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) { struct jffs2_inode_cache *ret; ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_inode_cache(struct jffs2_inode_cache *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(inode_cache_slab, x); } diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 9abb5f4cfd75..80fe8feffb4d 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.112 2005/08/22 09:07:09 dedekind Exp $ + * $Id: nodelist.c,v 1.114 2005/09/21 13:28:35 dedekind Exp $ * */ @@ -25,18 +25,18 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new { struct jffs2_full_dirent **prev = list; - JFFS2_DBG_DENTLIST("add dirent \"%s\", ino #%u\n", new->name, new->ino); + dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) { /* Duplicate. Free one */ if (new->version < (*prev)->version) { - JFFS2_DBG_DENTLIST("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", + dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", (*prev)->name, (*prev)->ino); jffs2_mark_node_obsolete(c, new->raw); jffs2_free_full_dirent(new); } else { - JFFS2_DBG_DENTLIST("marking old dirent \"%s\", ino #%u bsolete\n", + dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n", (*prev)->name, (*prev)->ino); new->next = (*prev)->next; jffs2_mark_node_obsolete(c, ((*prev)->raw)); @@ -55,7 +55,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); - JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); + dbg_fragtree("truncating fragtree to 0x%08x bytes\n", size); /* We know frag->ofs <= size. That's what lookup does for us */ if (frag && frag->ofs != size) { @@ -81,7 +81,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint */ frag = frag_last(list); if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { - JFFS2_DBG_FRAGTREE2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", + dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } @@ -93,12 +93,12 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t this->node->frags--; if (!this->node->frags) { /* The node has no valid frags left. It's totally obsoleted */ - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", + dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size); jffs2_mark_node_obsolete(c, this->node->raw); jffs2_free_full_dnode(this->node); } else { - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", + dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } @@ -112,7 +112,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ struct rb_node *parent = &base->rb; struct rb_node **link = &parent; - JFFS2_DBG_FRAGTREE2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); + dbg_fragtree2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); while (*link) { parent = *link; @@ -172,11 +172,11 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ - JFFS2_DBG_FRAGTREE2("add hole frag %#04x-%#04x on the right of the new frag.\n", + dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("Add hole frag %#04x-%#04x to the root of the tree.\n", + dbg_fragtree2("Add hole frag %#04x-%#04x to the root of the tree.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, NULL, &root->rb_node); } @@ -188,10 +188,10 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ - JFFS2_DBG_FRAGTREE2("add the new node at the right\n"); + dbg_fragtree2("add the new node at the right\n"); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("insert the new node at the root of the tree\n"); + dbg_fragtree2("insert the new node at the root of the tree\n"); rb_link_node(&newfrag->rb, NULL, &root->rb_node); } rb_insert_color(&newfrag->rb, root); @@ -209,11 +209,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this = jffs2_lookup_node_frag(root, newfrag->node->ofs); if (this) { - JFFS2_DBG_FRAGTREE2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + dbg_fragtree2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); lastend = this->ofs + this->size; } else { - JFFS2_DBG_FRAGTREE2("lookup gave no frag\n"); + dbg_fragtree2("lookup gave no frag\n"); lastend = 0; } @@ -235,11 +235,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } if (this->node) - JFFS2_DBG_FRAGTREE2("dealing with frag %u-%u, phys %#08x(%d).\n", + dbg_fragtree2("dealing with frag %u-%u, phys %#08x(%d).\n", this->ofs, this->ofs + this->size, ref_offset(this->node->raw), ref_flags(this->node->raw)); else - JFFS2_DBG_FRAGTREE2("dealing with hole frag %u-%u.\n", + dbg_fragtree2("dealing with hole frag %u-%u.\n", this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, @@ -259,10 +259,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r struct jffs2_node_frag *newfrag2; if (this->node) - JFFS2_DBG_FRAGTREE2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", + dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); else - JFFS2_DBG_FRAGTREE2("split old hole frag 0x%04x-0x%04x\n", + dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n", this->ofs, this->ofs+this->size); /* New second frag pointing to this's node */ @@ -299,13 +299,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } else { /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ - JFFS2_DBG_FRAGTREE2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", + dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); rb_replace_node(&this->rb, &newfrag->rb, root); if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); + dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); } else { this->ofs += newfrag->size; @@ -321,7 +321,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x) and removing from tree\n", + dbg_fragtree2("obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size); rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); @@ -361,7 +361,7 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in return -ENOMEM; newfrag->node->frags = 1; - JFFS2_DBG_FRAGTREE("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", + dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); @@ -410,14 +410,17 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info BUG_ON(tn->csize == 0); + if (!jffs2_is_writebuffered(c)) + goto adj_acc; + /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); - len = ofs & (c->wbuf_pagesize - 1); + len = ofs % c->wbuf_pagesize; if (likely(len)) len = c->wbuf_pagesize - len; if (len >= tn->csize) { - JFFS2_DBG_READINODE("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", + dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", ref_offset(ref), tn->csize, ofs); goto adj_acc; } @@ -425,7 +428,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info ofs += len; len = tn->csize - len; - JFFS2_DBG_READINODE("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); #ifndef __ECOS @@ -520,7 +523,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - JFFS2_DBG_FRAGTREE2("check node %#04x-%#04x, phys offs %#08x.\n", + dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); ret = check_node_data(c, tn); @@ -528,7 +531,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f JFFS2_ERROR("check_node_data() returned error: %d.\n", ret); } else if (unlikely(ret > 0)) { - JFFS2_DBG_FRAGTREE2("CRC error, mark it obsolete.\n"); + dbg_fragtree2("CRC error, mark it obsolete.\n"); jffs2_mark_node_obsolete(c, tn->fn->raw); } @@ -544,7 +547,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole) { - JFFS2_DBG_FRAGTREE2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", + dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); if (hole->ofs == newfrag->ofs) { @@ -558,7 +561,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, * the new node. */ - JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and cut the left part of the hole\n", + dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); @@ -576,7 +579,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, * Ah, the new fragment is of the same size as the hole. * Relace the hole by it. */ - JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and overwrite hole\n", + dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); jffs2_free_node_frag(hole); @@ -598,14 +601,14 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, } hole->size = newfrag->ofs - hole->ofs; - JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", + dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size); jffs2_fragtree_insert(newfrag, hole); rb_insert_color(&newfrag->rb, root); if (newfrag2) { - JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the right\n", + dbg_fragtree2("left the hole %#04x-%#04x at the right\n", newfrag2->ofs, newfrag2->ofs + newfrag2->size); jffs2_fragtree_insert(newfrag2, newfrag); rb_insert_color(&newfrag2->rb, root); @@ -640,12 +643,12 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode int err, checked = 0; int ref_flag; - JFFS2_DBG_FRAGTREE("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); + dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); /* Skip all the nodes which are completed before this one starts */ this = jffs2_lookup_node_frag(root, fn_ofs); if (this) - JFFS2_DBG_FRAGTREE2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); + dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); if (this) lastend = this->ofs + this->size; @@ -745,7 +748,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode * The new node starts at the same offset as * the hole and supersieds the hole. */ - JFFS2_DBG_FRAGTREE2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", + dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); rb_replace_node(&this->rb, &newfrag->rb, root); @@ -755,10 +758,10 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode * The hole becomes shorter as its right part * is supersieded by the new fragment. */ - JFFS2_DBG_FRAGTREE2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", + dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - JFFS2_DBG_FRAGTREE2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, + dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); this->size -= newfrag->size; @@ -771,7 +774,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this = rb_entry(rb_next(&newfrag->rb), struct jffs2_node_frag, rb); - JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } @@ -782,7 +785,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode if (this->ofs + this->size >= fn_ofs + fn_size) { /* The new node is obsolete, drop it */ if (fn->frags == 0) { - JFFS2_DBG_FRAGTREE2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); + dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); ref_flag = REF_OBSOLETE; } goto out_ok; @@ -790,13 +793,13 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode struct jffs2_node_frag *new_this; /* 'This' node obsoletes the beginning of the new node */ - JFFS2_DBG_FRAGTREE2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); + dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); ref_flag = REF_NORMAL; fn_size -= this->ofs + this->size - fn_ofs; fn_ofs = this->ofs + this->size; - JFFS2_DBG_FRAGTREE2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); + dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); if (!new_this) { @@ -816,14 +819,14 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode if (unlikely(!newfrag)) return -ENOMEM; - JFFS2_DBG_FRAGTREE2("there are no more fragments, insert %#04x-%#04x\n", + dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); rb_insert_color(&newfrag->rb, root); goto out_ok; } else { this = new_this; - JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } } @@ -833,13 +836,13 @@ out_ok: BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE); if (ref_flag == REF_OBSOLETE) { - JFFS2_DBG_FRAGTREE2("the node is obsolete now\n"); + dbg_fragtree2("the node is obsolete now\n"); /* jffs2_mark_node_obsolete() will adjust space accounting */ jffs2_mark_node_obsolete(c, fn->raw); return 1; } - JFFS2_DBG_FRAGTREE2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); + dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); /* Space accounting was adjusted at check_node_data() */ spin_lock(&c->erase_completion_lock); @@ -885,7 +888,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new if (!new->ino) new->ino = ++c->highest_ino; - JFFS2_DBG_INOCACHE("add %p (ino #%u)\n", new, new->ino); + dbg_inocache("add %p (ino #%u)\n", new, new->ino); prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; @@ -902,7 +905,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) { struct jffs2_inode_cache **prev; - JFFS2_DBG_INOCACHE("del %p (ino #%u)\n", old, old->ino); + dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; @@ -965,7 +968,7 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ struct jffs2_node_frag *prev = NULL; struct jffs2_node_frag *frag = NULL; - JFFS2_DBG_FRAGTREE2("root %p, offset %d\n", fragtree, offset); + dbg_fragtree2("root %p, offset %d\n", fragtree, offset); next = fragtree->rb_node; @@ -988,10 +991,10 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ and return the closest smaller one */ if (prev) - JFFS2_DBG_FRAGTREE2("no match. Returning frag %#04x-%#04x, closest previous\n", + dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n", prev->ofs, prev->ofs+prev->size); else - JFFS2_DBG_FRAGTREE2("returning NULL, empty fragtree\n"); + dbg_fragtree2("returning NULL, empty fragtree\n"); return prev; } @@ -1006,7 +1009,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) if (!root->rb_node) return; - JFFS2_DBG_FRAGTREE("killing\n"); + dbg_fragtree("killing\n"); frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 2cf576ae1120..2c938d1bffb0 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.126 2005/09/16 12:58:17 havasi Exp $ + * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $ * */ @@ -273,7 +273,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin if (jeb) { reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); - JFFS2_DBG_SUMMARY("minsize=%d , jeb->free=%d ," + dbg_summary("minsize=%d , jeb->free=%d ," "summary->size=%d , sumsize=%d\n", minsize, jeb->free_size, c->summary->sum_size, sumsize); @@ -291,7 +291,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin } /* Writing out the collected summary information */ - JFFS2_DBG_SUMMARY("generating summary for 0x%08x.\n", jeb->offset); + dbg_summary("generating summary for 0x%08x.\n", jeb->offset); ret = jffs2_sum_write_sumnode(c); if (ret) diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index e026888cf1cb..48ad4202fbb1 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.61 2005/09/07 08:34:54 havasi Exp $ + * $Id: os-linux.h,v 1.63 2005/09/21 11:55:21 dedekind Exp $ * */ @@ -80,8 +80,8 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf) #define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) -#define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) -#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) +#define jffs2_flush_wbuf_pad(c) ({ do{} while(0); (void)(c), 0; }) +#define jffs2_flush_wbuf_gc(c, i) ({ do{} while(0); (void)(c), (void) i, 0; }) #define jffs2_write_nand_badblock(c,jeb,bad_offset) (1) #define jffs2_nand_flash_setup(c) (0) #define jffs2_nand_flash_cleanup(c) do {} while(0) diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6f1e4a7ecd9f..08f8c5ec6118 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.141 2005/08/17 14:57:39 dedekind Exp $ + * $Id: readinode.c,v 1.142 2005/09/20 14:27:34 dedekind Exp $ * */ @@ -97,7 +97,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r while (ref && ref->next_in_ino) { if (!ref_obsolete(ref)) return ref; - JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); + dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); ref = ref->next_in_ino; } return NULL; @@ -274,7 +274,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref len = min_t(uint32_t, rdlen - sizeof(*rd), csize); tn->partial_crc = crc32(0, buf, len); - JFFS2_DBG_READINODE("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); + dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); /* If we actually calculated the whole data CRC * and it is wrong, drop the node. */ @@ -293,7 +293,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref */ struct jffs2_eraseblock *jeb; - JFFS2_DBG_READINODE("the node has no data.\n"); + dbg_readinode("the node has no data.\n"); jeb = &c->blocks[ref->flash_offset / c->sector_size]; len = ref_totlen(c, jeb, ref); @@ -327,7 +327,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref else // normal case... tn->fn->size = je32_to_cpu(rd->dsize); - JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", + dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); jffs2_add_tn_to_tree(tn, tnp); @@ -424,7 +424,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, len = right_size - *rdlen; } - JFFS2_DBG_READINODE("read more %d bytes\n", len); + dbg_readinode("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); if (err) { @@ -461,7 +461,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *mctime_ver = 0; - JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino); + dbg_readinode("ino #%u\n", f->inocache->ino); if (jffs2_is_writebuffered(c)) { /* @@ -531,7 +531,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf len = JFFS2_MIN_NODE_HEADER; } - JFFS2_DBG_READINODE("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); + dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); /* FIXME: point() */ err = jffs2_flash_read(c, ref_offset(ref), len, @@ -614,7 +614,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *fdp = ret_fd; kfree(buf); - JFFS2_DBG_READINODE("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", + dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); return 0; @@ -639,7 +639,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, size_t retlen; int ret; - JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); + dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); /* Grab all nodes relevant to this ino */ ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); @@ -659,7 +659,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); fn = tn->fn; ret = 1; - JFFS2_DBG_READINODE("consider node ver %u, phys offset " + dbg_readinode("consider node ver %u, phys offset " "%#08x(%d), range %u-%u.\n", tn->version, ref_offset(fn->raw), ref_flags(fn->raw), fn->ofs, fn->ofs + fn->size); @@ -703,7 +703,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_free_tmp_dnode_info(tn); if (ret) { - JFFS2_DBG_READINODE("delete dnode %u-%u.\n", + dbg_readinode("delete dnode %u-%u.\n", fn->ofs, fn->ofs + fn->size); jffs2_free_full_dnode(fn); } @@ -803,7 +803,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } f->target[je32_to_cpu(latest_node->csize)] = '\0'; - JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target); + dbg_readinode("symlink's target '%s' cached\n", f->target); } /* fall through... */ @@ -851,7 +851,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { - JFFS2_DBG_READINODE("read inode #%u\n", ino); + dbg_readinode("read inode #%u\n", ino); retry_inocache: spin_lock(&c->inocache_lock); @@ -870,7 +870,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* If it's in either of these states, we need to wait for whoever's got it to finish and put it back. */ - JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state); + dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); goto retry_inocache; @@ -897,7 +897,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, JFFS2_ERROR("cannot allocate inocache for root inode\n"); return -ENOMEM; } - JFFS2_DBG_READINODE("creating inocache for root inode\n"); + dbg_readinode("creating inocache for root inode\n"); memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); f->inocache->ino = f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 4e60ba8da197..8df7456472b8 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.122 2005/09/07 08:34:54 havasi Exp $ + * $Id: scan.c,v 1.124 2005/09/21 13:05:22 dedekind Exp $ * */ #include @@ -429,7 +429,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo noise = 10; - JFFS2_DBG_SUMMARY("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); + dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); scan_more: while(ofs < jeb->offset + c->sector_size) { @@ -684,7 +684,7 @@ scan_more: if (jffs2_sum_active()) { if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) { - JFFS2_DBG_SUMMARY("There is not enough space for " + dbg_summary("There is not enough space for " "summary information, disabling for this jeb!\n"); jffs2_sum_disable_collecting(s); } @@ -920,76 +920,34 @@ void jffs2_rotate_lists(struct jffs2_sb_info *c) x = count_list(&c->clean_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); - rotate_list((&c->clean_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", - list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); } x = count_list(&c->very_dirty_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); - rotate_list((&c->very_dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", - list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); } x = count_list(&c->dirty_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); - rotate_list((&c->dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", - list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); } x = count_list(&c->erasable_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - rotate_list((&c->erasable_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", - list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); } if (c->nr_erasing_blocks) { rotateby = pseudo_random % c->nr_erasing_blocks; - D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); - rotate_list((&c->erase_pending_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", - list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); } if (c->nr_free_blocks) { rotateby = pseudo_random % c->nr_free_blocks; - D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); - rotate_list((&c->free_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", - list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); } } diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index cb5dd8f11e73..1ebc81e4477d 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * $Id: summary.c,v 1.3 2005/09/21 14:43:07 dedekind Exp $ * */ @@ -38,17 +38,18 @@ int jffs2_sum_init(struct jffs2_sb_info *c) if (!c->summary->sum_buf) { JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); + kfree(c->summary); return -ENOMEM; } - JFFS2_DBG_SUMMARY("returned succesfully\n"); + dbg_summary("returned succesfully\n"); return 0; } void jffs2_sum_exit(struct jffs2_sb_info *c) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_disable_collecting(c->summary); @@ -71,13 +72,13 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) case JFFS2_NODETYPE_INODE: s->sum_size += JFFS2_SUMMARY_INODE_SIZE; s->sum_num++; - JFFS2_DBG_SUMMARY("inode (%u) added to summary\n", + dbg_summary("inode (%u) added to summary\n", je32_to_cpu(item->i.inode)); break; case JFFS2_NODETYPE_DIRENT: s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); s->sum_num++; - JFFS2_DBG_SUMMARY("dirent (%u) added to summary\n", + dbg_summary("dirent (%u) added to summary\n", je32_to_cpu(item->d.ino)); break; default: @@ -93,7 +94,7 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size) { - JFFS2_DBG_SUMMARY("called with %u\n", size); + dbg_summary("called with %u\n", size); s->sum_padded += size; return 0; } @@ -147,7 +148,7 @@ static void jffs2_sum_clean_collected(struct jffs2_summary *s) union jffs2_sum_mem *temp; if (!s->sum_list_head) { - JFFS2_DBG_SUMMARY("already empty\n"); + dbg_summary("already empty\n"); } while (s->sum_list_head) { temp = s->sum_list_head; @@ -161,14 +162,14 @@ static void jffs2_sum_clean_collected(struct jffs2_summary *s) void jffs2_sum_reset_collected(struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_clean_collected(s); s->sum_size = 0; } void jffs2_sum_disable_collecting(struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_clean_collected(s); s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; } @@ -182,7 +183,7 @@ int jffs2_sum_is_disabled(struct jffs2_summary *s) void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", + dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", c->summary->sum_size, c->summary->sum_num, s->sum_size, s->sum_num); @@ -260,16 +261,16 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, } case JFFS2_NODETYPE_PADDING: - JFFS2_DBG_SUMMARY("node PADDING\n"); + dbg_summary("node PADDING\n"); c->summary->sum_padded += je32_to_cpu(node->u.totlen); break; case JFFS2_NODETYPE_CLEANMARKER: - JFFS2_DBG_SUMMARY("node CLEANMARKER\n"); + dbg_summary("node CLEANMARKER\n"); break; case JFFS2_NODETYPE_SUMMARY: - JFFS2_DBG_SUMMARY("node SUMMARY\n"); + dbg_summary("node SUMMARY\n"); break; default: @@ -302,7 +303,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras sp = summary->sum; for (i=0; isum_num); i++) { - JFFS2_DBG_SUMMARY("processing summary index %d\n", i); + dbg_summary("processing summary index %d\n", i); switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { case JFFS2_NODETYPE_INODE: { @@ -311,7 +312,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ino = je32_to_cpu(spi->inode); - JFFS2_DBG_SUMMARY("Inode at 0x%08x\n", + dbg_summary("Inode at 0x%08x\n", jeb->offset + je32_to_cpu(spi->offset)); raw = jffs2_alloc_raw_node_ref(); @@ -353,7 +354,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras struct jffs2_sum_dirent_flash *spd; spd = sp; - JFFS2_DBG_SUMMARY("Dirent at 0x%08x\n", + dbg_summary("Dirent at 0x%08x\n", jeb->offset + je32_to_cpu(spd->offset)); fd = jffs2_alloc_full_dirent(spd->nsize+1); @@ -434,7 +435,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb sumsize = c->sector_size - ofs; ofs += jeb->offset; - JFFS2_DBG_SUMMARY("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", + dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", jeb->offset, ofs, sumsize); summary = kmalloc(sumsize, GFP_KERNEL); @@ -457,40 +458,40 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb crc = crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node header is corrupt (bad CRC or " + dbg_summary("Summary node header is corrupt (bad CRC or " "no summary at all)\n"); goto crc_err; } if (je32_to_cpu(summary->totlen) != sumsize) { - JFFS2_DBG_SUMMARY("Summary node is corrupt (wrong erasesize?)\n"); + dbg_summary("Summary node is corrupt (wrong erasesize?)\n"); goto crc_err; } crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); if (je32_to_cpu(summary->node_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node is corrupt (bad CRC)\n"); + dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); if (je32_to_cpu(summary->sum_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node data is corrupt (bad CRC)\n"); + dbg_summary("Summary node data is corrupt (bad CRC)\n"); goto crc_err; } if ( je32_to_cpu(summary->cln_mkr) ) { - JFFS2_DBG_SUMMARY("Summary : CLEANMARKER node \n"); + dbg_summary("Summary : CLEANMARKER node \n"); if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { - JFFS2_DBG_SUMMARY("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", + dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else if (jeb->first_node) { - JFFS2_DBG_SUMMARY("CLEANMARKER node not first node in block " + dbg_summary("CLEANMARKER node not first node in block " "(0x%08x)\n", jeb->offset); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else { @@ -644,7 +645,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock vecs[1].iov_base = c->summary->sum_buf; vecs[1].iov_len = datasize; - JFFS2_DBG_SUMMARY("JFFS2: writing out data to flash to pos : 0x%08x\n", + dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", jeb->offset + c->sector_size - jeb->free_size); spin_unlock(&c->erase_completion_lock); @@ -674,7 +675,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) int datasize, infosize, padsize, ret; struct jffs2_eraseblock *jeb; - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jeb = c->nextblock; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 86860dbc670c..11e05bc014f1 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.98 2005/09/07 08:34:55 havasi Exp $ + * $Id: wbuf.c,v 1.99 2005/09/21 16:11:04 dedekind Exp $ * */ @@ -33,9 +33,6 @@ static unsigned char *brokenbuf; /* max. erase failures before we mark a block bad */ #define MAX_ERASE_FAILURES 2 -/* two seconds timeout for timed wbuf-flushing */ -#define WBUF_FLUSH_TIMEOUT 2 * HZ - struct jffs2_inodirty { uint32_t ino; struct jffs2_inodirty *next; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 5087612ed9ac..fdc445b49e19 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.53 2005/09/07 08:34:56 havasi Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -95,12 +95,13 @@ struct jffs2_sb_info { to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; + uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER /* Write-behind buffer for NAND flash */ unsigned char *wbuf; uint32_t wbuf_ofs; uint32_t wbuf_len; - uint32_t wbuf_pagesize; struct jffs2_inodirty *wbuf_inodes; struct rw_semaphore wbuf_sem; /* Protects the write buffer */ -- cgit v1.2.3 From 2bc9764c4837c6b7da540b7a2592ec02f9a14e47 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Mon, 26 Sep 2005 12:37:25 +0100 Subject: [JFFS2] Rename jffs2_summary_node to jffs2_raw_summary Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/summary.c | 14 +++++++------- fs/jffs2/summary.h | 4 ++-- include/linux/jffs2.h | 12 +++++++----- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 1ebc81e4477d..308251266c6c 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.3 2005/09/21 14:43:07 dedekind Exp $ + * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $ * */ @@ -292,7 +292,7 @@ no_mem: /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_summary_node *summary, uint32_t *pseudo_random) + struct jffs2_raw_summary *summary, uint32_t *pseudo_random) { struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; @@ -428,7 +428,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb { struct jffs2_unknown_node crcnode; struct jffs2_raw_node_ref *cache_ref; - struct jffs2_summary_node *summary; + struct jffs2_raw_summary *summary; int ret, sumsize; uint32_t crc; @@ -468,14 +468,14 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb goto crc_err; } - crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); + crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) != crc) { dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } - crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); + crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary)); if (je32_to_cpu(summary->sum_crc) != crc) { dbg_summary("Summary node data is corrupt (bad CRC)\n"); @@ -560,7 +560,7 @@ crc_err: static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t infosize, uint32_t datasize, int padsize) { - struct jffs2_summary_node isum; + struct jffs2_raw_summary isum; union jffs2_sum_mem *temp; struct jffs2_sum_marker *sm; struct kvec vecs[2]; @@ -685,7 +685,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) } datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); - infosize = sizeof(struct jffs2_summary_node) + datasize; + infosize = sizeof(struct jffs2_raw_summary) + datasize; padsize = jeb->free_size - infosize; infosize += padsize; datasize += padsize; diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index e6b0a69acbd4..b7a678be1709 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.h,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $ * */ @@ -142,7 +142,7 @@ struct jffs2_sum_marker jint32_t magic; /* == JFFS2_SUM_MAGIC */ }; -#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_summary_node) + sizeof(struct jffs2_sum_marker)) +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker)) #ifdef CONFIG_JFFS2_SUMMARY /* SUMMARY SUPPORT ENABLED */ diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index acb51a3669a2..2788880368c4 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.37 2005/09/07 08:34:55 havasi Exp $ + * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ * */ @@ -151,9 +151,10 @@ struct jffs2_raw_inode uint8_t data[0]; } __attribute__((packed)); -struct jffs2_summary_node{ +struct jffs2_raw_summary +{ jint16_t magic; - jint16_t nodetype; /* = JFFS2_NODETYPE_INODE_SUM */ + jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */ jint32_t totlen; jint32_t hdr_crc; jint32_t sum_num; /* number of sum entries*/ @@ -164,11 +165,12 @@ struct jffs2_summary_node{ jint32_t sum[0]; /* inode summary info */ } __attribute__((packed)); -union jffs2_node_union { +union jffs2_node_union +{ struct jffs2_raw_inode i; struct jffs2_raw_dirent d; + struct jffs2_raw_summary s; struct jffs2_unknown_node u; - struct jffs2_summary_node s; }; #endif /* __LINUX_JFFS2_H__ */ -- cgit v1.2.3 From 87590e26ff4e7d57dfdaa81780b1b0d9e9970a4c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 27 Sep 2005 11:26:39 +0100 Subject: [MTD] OneNAND: Add missing files Simple bad block table source and header files Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_bbt.c | 246 ++++++++++++++++++++++++++++++++++++++ include/linux/mtd/bbm.h | 122 +++++++++++++++++++ 2 files changed, 368 insertions(+) create mode 100644 drivers/mtd/onenand/onenand_bbt.c create mode 100644 include/linux/mtd/bbm.h (limited to 'include') diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c new file mode 100644 index 000000000000..f40190f499e1 --- /dev/null +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -0,0 +1,246 @@ +/* + * linux/drivers/mtd/onenand/onenand_bbt.c + * + * Bad Block Table support for the OneNAND driver + * + * Copyright(c) 2005 Samsung Electronics + * Kyungmin Park + * + * Derived from nand_bbt.c + * + * TODO: + * Split BBT core and chip specific BBT. + */ + +#include +#include +#include +#include + +/** + * check_short_pattern - [GENERIC] check if a pattern is in the buffer + * @param buf the buffer to search + * @param len the length of buffer to search + * @param paglen the pagelength + * @param td search pattern descriptor + * + * Check for a pattern at the given place. Used to search bad block + * tables and good / bad block identifiers. Same as check_pattern, but + * no optional empty check and the pattern is expected to start + * at offset 0. + * + */ +static int check_short_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) +{ + int i; + uint8_t *p = buf; + + /* Compare the pattern */ + for (i = 0; i < td->len; i++) { + if (p[i] != td->pattern[i]) + return -1; + } + return 0; +} + +/** + * create_bbt - [GENERIC] Create a bad block table by scanning the device + * @param mtd MTD device structure + * @param buf temporary buffer + * @param bd descriptor for the good/bad block search pattern + * @param chip create the table for a specific chip, -1 read all chips. + * Applies only if NAND_BBT_PERCHIP option is set + * + * Create a bad block table by scanning the device + * for the given good/bad block identify pattern + */ +static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int i, j, numblocks, len, scanlen; + int startblock; + loff_t from; + size_t readlen, ooblen; + + printk(KERN_INFO "Scanning device for bad blocks\n"); + + len = 1; + + /* We need only read few bytes from the OOB area */ + scanlen = ooblen = 0; + readlen = bd->len; + + /* chip == -1 case only */ + /* Note that numblocks is 2 * (real numblocks) here; + * see i += 2 below as it makses shifting and masking less painful + */ + numblocks = mtd->size >> (bbm->bbt_erase_shift - 1); + startblock = 0; + from = 0; + + for (i = startblock; i < numblocks; ) { + int ret; + + for (j = 0; j < len; j++) { + size_t retlen; + + /* No need to read pages fully, + * just read required OOB bytes */ + ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs, + readlen, &retlen, &buf[0]); + + if (ret) + return ret; + + if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { + bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); + printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", + i >> 1, (unsigned int) from); + break; + } + } + i += 2; + from += (1 << bbm->bbt_erase_shift); + } + + return 0; +} + + +/** + * onenand_memory_bbt - [GENERIC] create a memory based bad block table + * @param mtd MTD device structure + * @param bd descriptor for the good/bad block search pattern + * + * The function creates a memory based bbt by scanning the device + * for manufacturer / software marked good / bad blocks + */ +static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + unsigned char data_buf[MAX_ONENAND_PAGESIZE]; + + bd->options &= ~NAND_BBT_SCANEMPTY; + return create_bbt(mtd, data_buf, bd, -1); +} + +/** + * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad + * @param mtd MTD device structure + * @param offs offset in the device + * @param allowbbt allow access to bad block table region + */ +static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int block; + uint8_t res; + + /* Get block number * 2 */ + block = (int) (offs >> (bbm->bbt_erase_shift - 1)); + res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; + + DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", + (unsigned int) offs, block >> 1, res); + + switch ((int) res) { + case 0x00: return 0; + case 0x01: return 1; + case 0x02: return allowbbt ? 0 : 1; + } + + return 1; +} + +/** + * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s) + * @param mtd MTD device structure + * @param bd descriptor for the good/bad block search pattern + * + * The function checks, if a bad block table(s) is/are already + * available. If not it scans the device for manufacturer + * marked good / bad blocks and writes the bad block table(s) to + * the selected place. + * + * The bad block table memory is allocated here. It must be freed + * by calling the onenand_free_bbt function. + * + */ +int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int len, ret = 0; + + len = mtd->size >> (this->erase_shift + 2); + /* Allocate memory (2bit per block) */ + bbm->bbt = kmalloc(len, GFP_KERNEL); + if (!bbm->bbt) { + printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); + return -ENOMEM; + } + /* Clear the memory bad block table */ + memset(bbm->bbt, 0x00, len); + + /* Set the bad block position */ + bbm->badblockpos = ONENAND_BADBLOCK_POS; + + /* Set erase shift */ + bbm->bbt_erase_shift = this->erase_shift; + + if (!bbm->isbad_bbt) + bbm->isbad_bbt = onenand_isbad_bbt; + + /* Scan the device to build a memory based bad block table */ + if ((ret = onenand_memory_bbt(mtd, bd))) { + printk(KERN_ERR "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n"); + kfree(bbm->bbt); + bbm->bbt = NULL; + } + + return ret; +} + +/* + * Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks. + */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr largepage_memorybased = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern, +}; + +/** + * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device + * @param mtd MTD device structure + * + * This function selects the default bad block table + * support for the device and calls the onenand_scan_bbt function + */ +int onenand_default_bbt(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm; + + this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL); + if (!this->bbm) + return -ENOMEM; + + bbm = this->bbm; + + memset(bbm, 0, sizeof(struct bbm_info)); + + /* 1KB page has same configuration as 2KB page */ + if (!bbm->badblock_pattern) + bbm->badblock_pattern = &largepage_memorybased; + + return onenand_scan_bbt(mtd, bbm->badblock_pattern); +} + +EXPORT_SYMBOL(onenand_scan_bbt); +EXPORT_SYMBOL(onenand_default_bbt); diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h new file mode 100644 index 000000000000..92b42cb7ed2e --- /dev/null +++ b/include/linux/mtd/bbm.h @@ -0,0 +1,122 @@ +/* + * linux/include/linux/mtd/bbm.h + * + * NAND family Bad Block Management (BBM) header file + * - Bad Block Table (BBT) implementation + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * Copyright (c) 2000-2005 + * Thomas Gleixner + * + */ +#ifndef __LINUX_MTD_BBM_H +#define __LINUX_MTD_BBM_H + +/* The maximum number of NAND chips in an array */ +#define NAND_MAX_CHIPS 8 + +/** + * struct nand_bbt_descr - bad block table descriptor + * @param options options for this descriptor + * @param pages the page(s) where we find the bbt, used with + * option BBT_ABSPAGE when bbt is searched, + * then we store the found bbts pages here. + * Its an array and supports up to 8 chips now + * @param offs offset of the pattern in the oob area of the page + * @param veroffs offset of the bbt version counter in the oob are of the page + * @param version version read from the bbt page during scan + * @param len length of the pattern, if 0 no pattern check is performed + * @param maxblocks maximum number of blocks to search for a bbt. This number of + * blocks is reserved at the end of the device + * where the tables are written. + * @param reserved_block_code if non-0, this pattern denotes a reserved + * (rather than bad) block in the stored bbt + * @param pattern pattern to identify bad block table or factory marked + * good / bad blocks, can be NULL, if len = 0 + * + * Descriptor for the bad block table marker and the descriptor for the + * pattern which identifies good and bad blocks. The assumption is made + * that the pattern and the version count are always located in the oob area + * of the first block. + */ +struct nand_bbt_descr { + int options; + int pages[NAND_MAX_CHIPS]; + int offs; + int veroffs; + uint8_t version[NAND_MAX_CHIPS]; + int len; + int maxblocks; + int reserved_block_code; + uint8_t *pattern; +}; + +/* Options for the bad block table descriptors */ + +/* The number of bits used per block in the bbt on the device */ +#define NAND_BBT_NRBITS_MSK 0x0000000F +#define NAND_BBT_1BIT 0x00000001 +#define NAND_BBT_2BIT 0x00000002 +#define NAND_BBT_4BIT 0x00000004 +#define NAND_BBT_8BIT 0x00000008 +/* The bad block table is in the last good block of the device */ +#define NAND_BBT_LASTBLOCK 0x00000010 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_ABSPAGE 0x00000020 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_SEARCH 0x00000040 +/* bbt is stored per chip on multichip devices */ +#define NAND_BBT_PERCHIP 0x00000080 +/* bbt has a version counter at offset veroffs */ +#define NAND_BBT_VERSION 0x00000100 +/* Create a bbt if none axists */ +#define NAND_BBT_CREATE 0x00000200 +/* Search good / bad pattern through all pages of a block */ +#define NAND_BBT_SCANALLPAGES 0x00000400 +/* Scan block empty during good / bad block scan */ +#define NAND_BBT_SCANEMPTY 0x00000800 +/* Write bbt if neccecary */ +#define NAND_BBT_WRITE 0x00001000 +/* Read and write back block contents when writing bbt */ +#define NAND_BBT_SAVECONTENT 0x00002000 +/* Search good / bad pattern on the first and the second page */ +#define NAND_BBT_SCAN2NDPAGE 0x00004000 + +/* The maximum number of blocks to scan for a bbt */ +#define NAND_BBT_SCAN_MAXBLOCKS 4 + +/* + * Constants for oob configuration + */ +#define ONENAND_BADBLOCK_POS 0 + +/** + * struct bbt_info - [GENERIC] Bad Block Table data structure + * @param bbt_erase_shift [INTERN] number of address bits in a bbt entry + * @param badblockpos [INTERN] position of the bad block marker in the oob area + * @param bbt [INTERN] bad block table pointer + * @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @param priv [OPTIONAL] pointer to private bbm date + */ +struct bbm_info { + int bbt_erase_shift; + int badblockpos; + int options; + + uint8_t *bbt; + + int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt); + + /* TODO Add more NAND specific fileds */ + struct nand_bbt_descr *badblock_pattern; + + void *priv; +}; + +/* OneNAND BBT interface */ +extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); +extern int onenand_default_bbt(struct mtd_info *mtd); + +#endif /* __LINUX_MTD_BBM_H */ -- cgit v1.2.3 From a41371eb6d9b368e53867cd85156f07371e9f72f Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 29 Sep 2005 03:55:31 +0100 Subject: [MTD] OneNAND: Power Management (PM) support Add suspend/resume Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 36 +++++++++++++++++++++++++++++++++--- include/linux/mtd/onenand.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 75d757882697..a002d4025b29 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -505,7 +505,7 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, * * Get the device and lock it for exclusive access */ -static void onenand_get_device(struct mtd_info *mtd, int new_state) +static int onenand_get_device(struct mtd_info *mtd, int new_state) { struct onenand_chip *this = mtd->priv; DECLARE_WAITQUEUE(wait, current); @@ -520,12 +520,18 @@ static void onenand_get_device(struct mtd_info *mtd, int new_state) spin_unlock(&this->chip_lock); break; } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(&this->chip_lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; + } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&this->wq, &wait); spin_unlock(&this->chip_lock); schedule(); remove_wait_queue(&this->wq, &wait); } + + return 0; } /** @@ -1440,6 +1446,30 @@ static int onenand_probe(struct mtd_info *mtd) return 0; } +/** + * onenand_suspend - [MTD Interface] Suspend the OneNAND flash + * @param mtd MTD device structure + */ +static int onenand_suspend(struct mtd_info *mtd) +{ + return onenand_get_device(mtd, FL_PM_SUSPENDED); +} + +/** + * onenand_resume - [MTD Interface] Resume the OneNAND flash + * @param mtd MTD device structure + */ +static void onenand_resume(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + onenand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not" + "in suspended state\n"); +} + /** * onenand_scan - [OneNAND Interface] Scan for the OneNAND device @@ -1527,8 +1557,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) mtd->sync = onenand_sync; mtd->lock = NULL; mtd->unlock = onenand_unlock; - mtd->suspend = NULL; - mtd->resume = NULL; + mtd->suspend = onenand_suspend; + mtd->resume = onenand_resume; mtd->block_isbad = onenand_block_isbad; mtd->block_markbad = onenand_block_markbad; mtd->owner = THIS_MODULE; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 58023082320a..afaa6342aa7f 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -36,6 +36,7 @@ typedef enum { FL_SYNCING, FL_UNLOCKING, FL_LOCKING, + FL_PM_SUSPENDED, } onenand_state_t; /** -- cgit v1.2.3 From 83a368380e172c1b2e9fd6ec2a62e457684adf0c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 29 Sep 2005 04:53:16 +0100 Subject: [MTD] OneNAND: Enhanced support for DDP (Dual Densitiy Packages) Add density mask for better support of DDP chips. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 39 ++++++++++++++++++-------------------- include/linux/mtd/onenand.h | 1 + 2 files changed, 19 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index a002d4025b29..99de2f055eb1 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -84,25 +84,23 @@ static void onenand_writew(unsigned short value, void __iomem *addr) /** * onenand_block_address - [DEFAULT] Get block address - * @param device the device id + * @param this onenand chip data structure * @param block the block * @return translated block address if DDP, otherwise same * * Setup Start Address 1 Register (F100h) */ -static int onenand_block_address(int device, int block) +static int onenand_block_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { + if (this->device_id & ONENAND_DEVICE_IS_DDP) { /* Device Flash Core select, NAND Flash Block Address */ - int dfs = 0, density, mask; + int dfs = 0; - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); - - if (block & mask) + if (block & this->density_mask) dfs = 1; - return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); + return (dfs << ONENAND_DDP_SHIFT) | + (block & (this->density_mask - 1)); } return block; @@ -110,22 +108,19 @@ static int onenand_block_address(int device, int block) /** * onenand_bufferram_address - [DEFAULT] Get bufferram address - * @param device the device id + * @param this onenand chip data structure * @param block the block * @return set DBS value if DDP, otherwise 0 * * Setup Start Address 2 Register (F101h) for DDP */ -static int onenand_bufferram_address(int device, int block) +static int onenand_bufferram_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { + if (this->device_id & ONENAND_DEVICE_IS_DDP) { /* Device BufferRAM Select */ - int dbs = 0, density, mask; - - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); + int dbs = 0; - if (block & mask) + if (block & this->density_mask) dbs = 1; return (dbs << ONENAND_DDP_SHIFT); @@ -223,7 +218,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le /* NOTE: The setting order of the registers is very important! */ if (cmd == ONENAND_CMD_BUFFERRAM) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); /* Switch to the next data buffer */ @@ -234,7 +229,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le if (block != -1) { /* Write 'DFS, FBA' of Flash */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); } @@ -263,7 +258,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le if (readcmd) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); } } @@ -1313,7 +1308,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) continue; /* Set block address for read block status */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); /* Check lock status */ @@ -1415,6 +1410,8 @@ static int onenand_probe(struct mtd_info *mtd) density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; this->chipsize = (16 << density) << 20; + /* Set density mask. it is used for DDP */ + this->density_mask = (1 << (density + 6)); /* OneNAND page size & block size */ /* The data buffer size is equal to page size */ diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index afaa6342aa7f..d27fd12d096d 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -84,6 +84,7 @@ struct onenand_chip { void __iomem *base; unsigned int chipsize; unsigned int device_id; + unsigned int density_mask; unsigned int options; unsigned int erase_shift; -- cgit v1.2.3 From fb0258730ad554db531f12fc1c3d5a5234fe52a4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 17 Oct 2005 22:03:19 +0100 Subject: [MTD] Don't let gcc inline functions marked __xipram If they get inlined into non __xipram functions we're screwed. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- include/linux/mtd/xip.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 7b7deef6b180..863fa5a1d24e 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $ + * $Id: xip.h,v 1.4 2005/10/17 21:03:16 nico Exp $ */ #ifndef __LINUX_MTD_XIP_H__ @@ -22,19 +22,19 @@ #ifdef CONFIG_MTD_XIP -/* - * Function that are modifying the flash state away from array mode must - * obviously not be running from flash. The __xipram is therefore marking - * those functions so they get relocated to ram. - */ -#define __xipram __attribute__ ((__section__ (".data"))) - /* * We really don't want gcc to guess anything. * We absolutely _need_ proper inlining. */ #include +/* + * Function that are modifying the flash state away from array mode must + * obviously not be running from flash. The __xipram is therefore marking + * those functions so they get relocated to ram. + */ +#define __xipram noinline __attribute__ ((__section__ (".data"))) + /* * Each architecture has to provide the following macros. They must access * the hardware directly and not rely on any other (XIP) functions since they -- cgit v1.2.3 From 3c726f8dee6f55e96475574e9f645327e461884c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 11:06:55 +1100 Subject: [PATCH] ppc64: support 64k pages Adds a new CONFIG_PPC_64K_PAGES which, when enabled, changes the kernel base page size to 64K. The resulting kernel still boots on any hardware. On current machines with 4K pages support only, the kernel will maintain 16 "subpages" for each 64K page transparently. Note that while real 64K capable HW has been tested, the current patch will not enable it yet as such hardware is not released yet, and I'm still verifying with the firmware architects the proper to get the information from the newer hypervisors. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- arch/powerpc/Kconfig | 9 + arch/powerpc/kernel/asm-offsets.c | 3 + arch/powerpc/kernel/cputable.c | 4 +- arch/powerpc/kernel/head_64.S | 300 +++++++++++---- arch/powerpc/kernel/lparmap.c | 2 +- arch/powerpc/kernel/process.c | 6 +- arch/powerpc/kernel/prom.c | 76 ++-- arch/powerpc/kernel/setup_64.c | 31 +- arch/powerpc/lib/copypage_64.S | 2 +- arch/powerpc/lib/copyuser_64.S | 4 +- arch/powerpc/mm/hash_low_64.S | 613 +++++++++++++++++++++++++++++-- arch/powerpc/mm/hash_native_64.c | 377 +++++++++++-------- arch/powerpc/mm/hash_utils_64.c | 532 +++++++++++++++++++++------ arch/powerpc/mm/hugetlbpage.c | 134 ++++--- arch/powerpc/mm/init_64.c | 18 +- arch/powerpc/mm/mem.c | 56 ++- arch/powerpc/mm/pgtable_64.c | 22 +- arch/powerpc/mm/ppc_mmu_32.c | 15 + arch/powerpc/mm/slb.c | 102 ++++- arch/powerpc/mm/slb_low.S | 220 +++++++---- arch/powerpc/mm/stab.c | 30 +- arch/powerpc/mm/tlb_64.c | 32 +- arch/powerpc/platforms/iseries/htab.c | 65 ++-- arch/powerpc/platforms/iseries/hvlog.c | 4 +- arch/powerpc/platforms/iseries/iommu.c | 74 ++-- arch/powerpc/platforms/iseries/setup.c | 13 +- arch/powerpc/platforms/iseries/vio.c | 39 +- arch/powerpc/platforms/iseries/viopath.c | 16 +- arch/powerpc/platforms/pseries/lpar.c | 115 +++--- arch/ppc64/Kconfig | 13 + arch/ppc64/kernel/asm-offsets.c | 3 + arch/ppc64/kernel/head.S | 300 +++++++++++---- arch/ppc64/kernel/pacaData.c | 2 +- arch/ppc64/kernel/prom.c | 94 ++--- include/asm-powerpc/cputable.h | 3 + include/asm-powerpc/iommu.h | 5 + include/asm-powerpc/machdep.h | 10 +- include/asm-powerpc/prom.h | 8 + include/asm-powerpc/system.h | 2 +- include/asm-powerpc/thread_info.h | 20 +- include/asm-powerpc/tlbflush.h | 9 +- include/asm-ppc64/mmu.h | 208 ++++++----- include/asm-ppc64/mmu_context.h | 15 +- include/asm-ppc64/paca.h | 13 +- include/asm-ppc64/page.h | 147 ++++++-- include/asm-ppc64/pgalloc.h | 47 ++- include/asm-ppc64/pgtable-4k.h | 88 +++++ include/asm-ppc64/pgtable-64k.h | 87 +++++ include/asm-ppc64/pgtable.h | 160 +++----- include/asm-ppc64/prom.h | 8 + include/asm-ppc64/system.h | 2 +- mm/hugetlb.c | 3 + 52 files changed, 2949 insertions(+), 1212 deletions(-) create mode 100644 include/asm-ppc64/pgtable-4k.h create mode 100644 include/asm-ppc64/pgtable-64k.h (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index f4e25c648fbb..ca7acb0c79f0 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -603,6 +603,15 @@ config NODES_SPAN_OTHER_NODES def_bool y depends on NEED_MULTIPLE_NODES +config PPC_64K_PAGES + bool "64k page size" + help + This option changes the kernel logical page size to 64k. On machines + without processor support for 64k pages, the kernel will simulate + them by loading each individual 4k page on demand transparently, + while on hardware with such support, it will be used to map + normal application pages. + config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on PPC64 && SMP diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index bc5a3689cc05..b75757251994 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -125,6 +125,9 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); +#ifdef CONFIG_PPC_64K_PAGES + DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); +#endif #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index b91345fa0805..33c63bcf69f8 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -240,7 +240,7 @@ struct cpu_spec cpu_specs[] = { .oprofile_model = &op_model_power4, #endif }, - { /* Power5 */ + { /* Power5 GR */ .pvr_mask = 0xffff0000, .pvr_value = 0x003a0000, .cpu_name = "POWER5 (gr)", @@ -255,7 +255,7 @@ struct cpu_spec cpu_specs[] = { .oprofile_model = &op_model_power4, #endif }, - { /* Power5 */ + { /* Power5 GS */ .pvr_mask = 0xffff0000, .pvr_value = 0x003b0000, .cpu_name = "POWER5 (gs)", diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 45d81976987f..16ab40daa738 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -195,11 +195,11 @@ exception_marker: #define EX_R12 24 #define EX_R13 32 #define EX_SRR0 40 -#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */ #define EX_DAR 48 -#define EX_LR 48 /* SLB miss saves LR, but not DAR */ #define EX_DSISR 56 #define EX_CCR 60 +#define EX_R3 64 +#define EX_LR 72 #define EXCEPTION_PROLOG_PSERIES(area, label) \ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ @@ -419,17 +419,22 @@ data_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_DAR std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_DAR - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x400, instruction_access) @@ -440,17 +445,22 @@ instruction_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) STD_EXCEPTION_PSERIES(0x600, alignment) @@ -508,6 +518,38 @@ _GLOBAL(do_stab_bolted_pSeries) mfspr r12,SPRN_SPRG2 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) +/* + * We have some room here we use that to put + * the peries slb miss user trampoline code so it's reasonably + * away from slb_miss_user_common to avoid problems with rfid + * + * This is used for when the SLB miss handler has to go virtual, + * which doesn't happen for now anymore but will once we re-implement + * dynamic VSIDs for shared page tables + */ +#ifdef __DISABLED__ +slb_miss_user_pseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + clrrdi r12,r13,32 + mfmsr r10 + mfspr r11,SRR0 /* save SRR0 */ + ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ + ori r10,r10,MSR_IR|MSR_DR|MSR_RI + mtspr SRR0,r12 + mfspr r12,SRR1 /* and SRR1 */ + mtspr SRR1,r10 + rfid + b . /* prevent spec. execution */ +#endif /* __DISABLED__ */ + /* * Vectors for the FWNMI option. Share common code. */ @@ -559,22 +601,59 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) .globl data_access_slb_iSeries data_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) mfspr r3,SPRN_DAR - b .do_slb_miss + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) .globl instruction_access_slb_iSeries instruction_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) - ld r3,PACALPPACA+LPPACASRR0(r13) - b .do_slb_miss + ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge .slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode + +#ifdef __DISABLED__ +slb_miss_user_iseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + EXCEPTION_PROLOG_ISERIES_2 + b slb_miss_user_common +#endif MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) @@ -809,6 +888,126 @@ instruction_access_common: li r5,0x400 b .do_hash_page /* Try to handle as hpte fault */ +/* + * Here is the common SLB miss user that is used when going to virtual + * mode for SLB misses, that is currently not used + */ +#ifdef __DISABLED__ + .align 7 + .globl slb_miss_user_common +slb_miss_user_common: + mflr r10 + std r3,PACA_EXGEN+EX_DAR(r13) + stw r9,PACA_EXGEN+EX_CCR(r13) + std r10,PACA_EXGEN+EX_LR(r13) + std r11,PACA_EXGEN+EX_SRR0(r13) + bl .slb_allocate_user + + ld r10,PACA_EXGEN+EX_LR(r13) + ld r3,PACA_EXGEN+EX_R3(r13) + lwz r9,PACA_EXGEN+EX_CCR(r13) + ld r11,PACA_EXGEN+EX_SRR0(r13) + mtlr r10 + beq- slb_miss_fault + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_user_slb + mfmsr r10 + +.machine push +.machine "power4" + mtcrf 0x80,r9 +.machine pop + + clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ + mtmsrd r10,1 + + mtspr SRR0,r11 + mtspr SRR1,r12 + + ld r9,PACA_EXGEN+EX_R9(r13) + ld r10,PACA_EXGEN+EX_R10(r13) + ld r11,PACA_EXGEN+EX_R11(r13) + ld r12,PACA_EXGEN+EX_R12(r13) + ld r13,PACA_EXGEN+EX_R13(r13) + rfid + b . + +slb_miss_fault: + EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) + ld r4,PACA_EXGEN+EX_DAR(r13) + li r5,0 + std r4,_DAR(r1) + std r5,_DSISR(r1) + b .handle_page_fault + +unrecov_user_slb: + EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + +#endif /* __DISABLED__ */ + + +/* + * r13 points to the PACA, r9 contains the saved CR, + * r12 contain the saved SRR1, SRR0 is still ready for return + * r3 has the faulting address + * r9 - r13 are saved in paca->exslb. + * r3 is saved in paca->slb_r3 + * We assume we aren't going to take any exceptions during this procedure. + */ +_GLOBAL(slb_miss_realmode) + mflr r10 + + stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ + std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ + + bl .slb_allocate_realmode + + /* All done -- return from exception. */ + + ld r10,PACA_EXSLB+EX_LR(r13) + ld r3,PACA_EXSLB+EX_R3(r13) + lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ +#ifdef CONFIG_PPC_ISERIES + ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ +#endif /* CONFIG_PPC_ISERIES */ + + mtlr r10 + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_slb + +.machine push +.machine "power4" + mtcrf 0x80,r9 + mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ +.machine pop + +#ifdef CONFIG_PPC_ISERIES + mtspr SPRN_SRR0,r11 + mtspr SPRN_SRR1,r12 +#endif /* CONFIG_PPC_ISERIES */ + ld r9,PACA_EXSLB+EX_R9(r13) + ld r10,PACA_EXSLB+EX_R10(r13) + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) + rfid + b . /* prevent speculative execution */ + +unrecov_slb: + EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + .align 7 .globl hardware_interrupt_common .globl hardware_interrupt_entry @@ -1138,62 +1337,6 @@ _GLOBAL(do_stab_bolted) rfid b . /* prevent speculative execution */ -/* - * r13 points to the PACA, r9 contains the saved CR, - * r11 and r12 contain the saved SRR0 and SRR1. - * r3 has the faulting address - * r9 - r13 are saved in paca->exslb. - * r3 is saved in paca->slb_r3 - * We assume we aren't going to take any exceptions during this procedure. - */ -_GLOBAL(do_slb_miss) - mflr r10 - - stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ - std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ - - bl .slb_allocate /* handle it */ - - /* All done -- return from exception. */ - - ld r10,PACA_EXSLB+EX_LR(r13) - ld r3,PACA_EXSLB+EX_R3(r13) - lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ -#ifdef CONFIG_PPC_ISERIES - ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ -#endif /* CONFIG_PPC_ISERIES */ - - mtlr r10 - - andi. r10,r12,MSR_RI /* check for unrecoverable exception */ - beq- unrecov_slb - -.machine push -.machine "power4" - mtcrf 0x80,r9 - mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ -.machine pop - -#ifdef CONFIG_PPC_ISERIES - mtspr SPRN_SRR0,r11 - mtspr SPRN_SRR1,r12 -#endif /* CONFIG_PPC_ISERIES */ - ld r9,PACA_EXSLB+EX_R9(r13) - ld r10,PACA_EXSLB+EX_R10(r13) - ld r11,PACA_EXSLB+EX_R11(r13) - ld r12,PACA_EXSLB+EX_R12(r13) - ld r13,PACA_EXSLB+EX_R13(r13) - rfid - b . /* prevent speculative execution */ - -unrecov_slb: - EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) - DISABLE_INTS - bl .save_nvgprs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl .unrecoverable_exception - b 1b - /* * Space for CPU0's segment table. * @@ -1569,7 +1712,10 @@ _GLOBAL(__secondary_start) #endif /* Initialize the first segment table (or SLB) entry */ ld r3,PACASTABVIRT(r13) /* get addr of segment table */ +BEGIN_FTR_SECTION bl .stab_initialize +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) + bl .slb_initialize /* Initialize the kernel stack. Just a repeat for iSeries. */ LOADADDR(r3,current_set) diff --git a/arch/powerpc/kernel/lparmap.c b/arch/powerpc/kernel/lparmap.c index eded971d1bf9..5a05a797485f 100644 --- a/arch/powerpc/kernel/lparmap.c +++ b/arch/powerpc/kernel/lparmap.c @@ -25,7 +25,7 @@ const struct LparMap __attribute__((__section__(".text"))) xLparMap = { .xRanges = { { .xPages = HvPagesToMap, .xOffset = 0, - .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT), + .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - HW_PAGE_SHIFT), }, }, }; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 96843211cc5c..7f64f0464d44 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -554,12 +554,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_SLB)) { unsigned long sp_vsid = get_kernel_vsid(sp); + unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; sp_vsid <<= SLB_VSID_SHIFT; - sp_vsid |= SLB_VSID_KERNEL; - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - sp_vsid |= SLB_VSID_L; - + sp_vsid |= SLB_VSID_KERNEL | llp; p->thread.ksp_vsid = sp_vsid; } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index eec2da695508..3675ef4bac90 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -724,10 +724,10 @@ static inline char *find_flat_dt_string(u32 offset) * used to extract the memory informations at boot before we can * unflatten the tree */ -static int __init scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) { unsigned long p = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; @@ -784,8 +784,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node, * This function can be used within scan_flattened_dt callback to get * access to properties */ -static void* __init get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) { unsigned long p = node; @@ -1087,7 +1087,7 @@ void __init unflatten_device_tree(void) static int __init early_init_dt_scan_cpus(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); u32 *prop; unsigned long size = 0; @@ -1095,19 +1095,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, if (type == NULL || strcmp(type, "cpu") != 0) return 0; -#ifdef CONFIG_PPC_PSERIES - /* On LPAR, look for the first ibm,pft-size property for the hash table size - */ - if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) { - u32 *pft_size; - pft_size = get_flat_dt_prop(node, "ibm,pft-size", NULL); - if (pft_size != NULL) { - /* pft_size[0] is the NUMA CEC cookie */ - ppc64_pft_size = pft_size[1]; - } - } -#endif - boot_cpuid = 0; boot_cpuid_phys = 0; if (initial_boot_params && initial_boot_params->version >= 2) { @@ -1117,8 +1104,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; } else { /* Check if it's the boot-cpu, set it's hw index now */ - if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { - prop = get_flat_dt_prop(node, "reg", NULL); + if (of_get_flat_dt_prop(node, + "linux,boot-cpu", NULL) != NULL) { + prop = of_get_flat_dt_prop(node, "reg", NULL); if (prop != NULL) boot_cpuid_phys = *prop; } @@ -1127,14 +1115,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node, #ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", &size); + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size); if (prop && (*prop) > 0) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } /* Same goes for Apple's "altivec" property */ - prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); if (prop) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; @@ -1147,7 +1135,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, * this by looking at the size of the ibm,ppc-interrupt-server#s * property */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &size); cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; if (prop && ((size / sizeof(u32)) > 1)) @@ -1170,7 +1158,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 0; /* get platform type */ - prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); if (prop == NULL) return 0; #ifdef CONFIG_PPC64 @@ -1183,21 +1171,21 @@ static int __init early_init_dt_scan_chosen(unsigned long node, #ifdef CONFIG_PPC64 /* check if iommu is forced on or off */ - if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) iommu_is_off = 1; - if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) iommu_force_on = 1; #endif - lprop = get_flat_dt_prop(node, "linux,memory-limit", NULL); + lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); if (lprop) memory_limit = *lprop; #ifdef CONFIG_PPC64 - lprop = get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); if (lprop) tce_alloc_start = *lprop; - lprop = get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); if (lprop) tce_alloc_end = *lprop; #endif @@ -1209,9 +1197,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node, { u64 *basep, *entryp; - basep = get_flat_dt_prop(node, "linux,rtas-base", NULL); - entryp = get_flat_dt_prop(node, "linux,rtas-entry", NULL); - prop = get_flat_dt_prop(node, "linux,rtas-size", NULL); + basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); + entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); + prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); if (basep && entryp && prop) { rtas.base = *basep; rtas.entry = *entryp; @@ -1232,11 +1220,11 @@ static int __init early_init_dt_scan_root(unsigned long node, if (depth != 0) return 0; - prop = get_flat_dt_prop(node, "#size-cells", NULL); + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); dt_root_size_cells = (prop == NULL) ? 1 : *prop; DBG("dt_root_size_cells = %x\n", dt_root_size_cells); - prop = get_flat_dt_prop(node, "#address-cells", NULL); + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); dt_root_addr_cells = (prop == NULL) ? 2 : *prop; DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); @@ -1271,7 +1259,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); cell_t *reg, *endp; unsigned long l; @@ -1279,7 +1267,7 @@ static int __init early_init_dt_scan_memory(unsigned long node, if (type == NULL || strcmp(type, "memory") != 0) return 0; - reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); + reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); if (reg == NULL) return 0; @@ -1343,12 +1331,12 @@ void __init early_init_devtree(void *params) * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... */ - scan_flat_dt(early_init_dt_scan_chosen, NULL); + of_scan_flat_dt(early_init_dt_scan_chosen, NULL); /* Scan memory nodes and rebuild LMBs */ lmb_init(); - scan_flat_dt(early_init_dt_scan_root, NULL); - scan_flat_dt(early_init_dt_scan_memory, NULL); + of_scan_flat_dt(early_init_dt_scan_root, NULL); + of_scan_flat_dt(early_init_dt_scan_memory, NULL); lmb_enforce_memory_limit(memory_limit); lmb_analyze(); #ifdef CONFIG_PPC64 @@ -1363,10 +1351,10 @@ void __init early_init_devtree(void *params) DBG("Scanning CPUs ...\n"); - /* Retreive hash table size from flattened tree plus other - * CPU related informations (altivec support, boot CPU ID, ...) + /* Retreive CPU related informations from the flat tree + * (altivec support, boot CPU ID, ...) */ - scan_flat_dt(early_init_dt_scan_cpus, NULL); + of_scan_flat_dt(early_init_dt_scan_cpus, NULL); DBG(" <- early_init_devtree()\n"); } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6b52cce872be..b0994050024f 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -277,16 +277,21 @@ void __init early_setup(unsigned long dt_ptr) DBG("Found, Initializing memory management...\n"); /* - * Initialize stab / SLB management + * Initialize the MMU Hash table and create the linear mapping + * of memory. Has to be done before stab/slb initialization as + * this is currently where the page size encoding is obtained */ - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - stab_initialize(lpaca->stab_real); + htab_initialize(); /* - * Initialize the MMU Hash table and create the linear mapping - * of memory + * Initialize stab / SLB management except on iSeries */ - htab_initialize(); + if (!firmware_has_feature(FW_FEATURE_ISERIES)) { + if (cpu_has_feature(CPU_FTR_SLB)) + slb_initialize(); + else + stab_initialize(lpaca->stab_real); + } DBG(" <- early_setup()\n"); } @@ -552,10 +557,12 @@ static void __init irqstack_early_init(void) * SLB misses on them. */ for_each_cpu(i) { - softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, - THREAD_SIZE, 0x10000000)); - hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, - THREAD_SIZE, 0x10000000)); + softirq_ctx[i] = (struct thread_info *) + __va(lmb_alloc_base(THREAD_SIZE, + THREAD_SIZE, 0x10000000)); + hardirq_ctx[i] = (struct thread_info *) + __va(lmb_alloc_base(THREAD_SIZE, + THREAD_SIZE, 0x10000000)); } } #else @@ -583,8 +590,8 @@ static void __init emergency_stack_init(void) limit = min(0x10000000UL, lmb.rmo_size); for_each_cpu(i) - paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128, - limit)) + PAGE_SIZE; + paca[i].emergency_sp = + __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE; } /* diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S index 733d61618bbf..40523b140109 100644 --- a/arch/powerpc/lib/copypage_64.S +++ b/arch/powerpc/lib/copypage_64.S @@ -11,7 +11,7 @@ #include #include -_GLOBAL(copy_page) +_GLOBAL(copy_4K_page) std r31,-8(1) std r30,-16(1) std r29,-24(1) diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index a0b3fbbd6fb1..6d69ef39b7df 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user) std r4,-16(r1) std r5,-8(r1) dcbt 0,r4 - beq .Lcopy_page + beq .Lcopy_page_4K andi. r6,r6,7 mtcrf 0x01,r5 blt cr1,.Lshort_copy @@ -366,7 +366,7 @@ _GLOBAL(__copy_tofrom_user) * above (following the .Ldst_aligned label) but it runs slightly * slower on POWER3. */ -.Lcopy_page: +.Lcopy_page_4K: std r31,-32(1) std r30,-40(1) std r29,-48(1) diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index d6ed9102eeea..e0d02c4a2615 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -1,7 +1,7 @@ /* * ppc64 MMU hashtable management routines * - * (c) Copyright IBM Corp. 2003 + * (c) Copyright IBM Corp. 2003, 2005 * * Maintained by: Benjamin Herrenschmidt * @@ -10,6 +10,7 @@ * described in the kernel's COPYING file. */ +#include #include #include #include @@ -42,14 +43,24 @@ /* Save non-volatile offsets */ #define STK_REG(i) (112 + ((i)-14)*8) + +#ifndef CONFIG_PPC_64K_PAGES + +/***************************************************************************** + * * + * 4K SW & 4K HW pages implementation * + * * + *****************************************************************************/ + + /* - * _hash_page(unsigned long ea, unsigned long access, unsigned long vsid, - * pte_t *ptep, unsigned long trap, int local) + * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, + * pte_t *ptep, unsigned long trap, int local) * - * Adds a page to the hash table. This is the non-LPAR version for now + * Adds a 4K page to the hash table in a segment of 4K pages only */ -_GLOBAL(__hash_page) +_GLOBAL(__hash_page_4K) mflr r0 std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) @@ -88,7 +99,8 @@ _GLOBAL(__hash_page) /* If so, just bail out and refault if needed. Someone else * is changing this PTE anyway and might hash it. */ - bne- bail_ok + bne- htab_bail_ok + /* Prepare new PTE value (turn access RW into DIRTY, then * add BUSY,HASHPTE and ACCESSED) */ @@ -118,10 +130,10 @@ _GLOBAL(__hash_page) /* Convert linux PTE bits into HW equivalents */ andi. r3,r30,0x1fe /* Get basic set of flags */ - xori r3,r3,HW_NO_EXEC /* _PAGE_EXEC -> NOEXEC */ + xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */ rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ - and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ @@ -158,19 +170,21 @@ htab_insert_pte: andc r30,r30,r0 ori r30,r30,_PAGE_HASHPTE - /* page number in r5 */ - rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT + /* physical address r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT /* Calculate primary group hash */ and r0,r28,r27 - rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ mr r4,r29 /* Retreive va */ - li r6,0 /* no vflags */ + li r7,0 /* !bolted, !secondary */ + li r8,MMU_PAGE_4K /* page size */ _GLOBAL(htab_call_hpte_insert1) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ cmpdi 0,r3,0 bge htab_pte_insert_ok /* Insertion successful */ cmpdi 0,r3,-2 /* Critical failure */ @@ -178,19 +192,21 @@ _GLOBAL(htab_call_hpte_insert1) /* Now try secondary slot */ - /* page number in r5 */ - rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT + /* physical address r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT /* Calculate secondary group hash */ andc r0,r27,r28 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ mr r4,r29 /* Retreive va */ - li r6,HPTE_V_SECONDARY@l /* secondary slot */ + li r7,HPTE_V_SECONDARY /* !bolted, secondary */ + li r8,MMU_PAGE_4K /* page size */ _GLOBAL(htab_call_hpte_insert2) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ cmpdi 0,r3,0 bge+ htab_pte_insert_ok /* Insertion successful */ cmpdi 0,r3,-2 /* Critical failure */ @@ -207,14 +223,14 @@ _GLOBAL(htab_call_hpte_insert2) rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ /* Call ppc_md.hpte_remove */ _GLOBAL(htab_call_hpte_remove) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ /* Try all again */ b htab_insert_pte -bail_ok: +htab_bail_ok: li r3,0 - b bail + b htab_bail htab_pte_insert_ok: /* Insert slot number & secondary bit in PTE */ @@ -227,7 +243,7 @@ htab_write_out_pte: ld r6,STK_PARM(r6)(r1) std r30,0(r6) li r3, 0 -bail: +htab_bail: ld r27,STK_REG(r27)(r1) ld r28,STK_REG(r28)(r1) ld r29,STK_REG(r29)(r1) @@ -256,10 +272,10 @@ htab_modify_pte: /* Call ppc_md.hpte_updatepp */ mr r5,r29 /* va */ - li r6,0 /* large is 0 */ + li r6,MMU_PAGE_4K /* page size */ ld r7,STK_PARM(r8)(r1) /* get "local" param */ _GLOBAL(htab_call_hpte_updatepp) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ /* if we failed because typically the HPTE wasn't really here * we try an insertion. @@ -276,13 +292,556 @@ htab_wrong_access: /* Bail out clearing reservation */ stdcx. r31,0,r6 li r3,1 - b bail + b htab_bail + +htab_pte_insert_failure: + /* Bail out restoring old PTE */ + ld r6,STK_PARM(r6)(r1) + std r31,0(r6) + li r3,-1 + b htab_bail + + +#else /* CONFIG_PPC_64K_PAGES */ + + +/***************************************************************************** + * * + * 64K SW & 4K or 64K HW in a 4K segment pages implementation * + * * + *****************************************************************************/ + +/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, + * pte_t *ptep, unsigned long trap, int local) + */ + +/* + * For now, we do NOT implement Admixed pages + */ +_GLOBAL(__hash_page_4K) + mflr r0 + std r0,16(r1) + stdu r1,-STACKFRAMESIZE(r1) + /* Save all params that we need after a function call */ + std r6,STK_PARM(r6)(r1) + std r8,STK_PARM(r8)(r1) + + /* Add _PAGE_PRESENT to access */ + ori r4,r4,_PAGE_PRESENT + + /* Save non-volatile registers. + * r31 will hold "old PTE" + * r30 is "new PTE" + * r29 is "va" + * r28 is a hash value + * r27 is hashtab mask (maybe dynamic patched instead ?) + * r26 is the hidx mask + * r25 is the index in combo page + */ + std r25,STK_REG(r25)(r1) + std r26,STK_REG(r26)(r1) + std r27,STK_REG(r27)(r1) + std r28,STK_REG(r28)(r1) + std r29,STK_REG(r29)(r1) + std r30,STK_REG(r30)(r1) + std r31,STK_REG(r31)(r1) + + /* Step 1: + * + * Check permissions, atomically mark the linux PTE busy + * and hashed. + */ +1: + ldarx r31,0,r6 + /* Check access rights (access & ~(pte_val(*ptep))) */ + andc. r0,r4,r31 + bne- htab_wrong_access + /* Check if PTE is busy */ + andi. r0,r31,_PAGE_BUSY + /* If so, just bail out and refault if needed. Someone else + * is changing this PTE anyway and might hash it. + */ + bne- htab_bail_ok + /* Prepare new PTE value (turn access RW into DIRTY, then + * add BUSY and ACCESSED) + */ + rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ + or r30,r30,r31 + ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + /* Write the linux PTE atomically (setting busy) */ + stdcx. r30,0,r6 + bne- 1b + isync + + /* Step 2: + * + * Insert/Update the HPTE in the hash table. At this point, + * r4 (access) is re-useable, we use it for the new HPTE flags + */ + + /* Load the hidx index */ + rldicl r25,r3,64-12,60 + + /* Calc va and put it in r29 */ + rldicr r29,r5,28,63-28 /* r29 = (vsid << 28) */ + rldicl r3,r3,0,36 /* r3 = (ea & 0x0fffffff) */ + or r29,r3,r29 /* r29 = va + + /* Calculate hash value for primary slot and store it in r28 */ + rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */ + rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */ + xor r28,r5,r0 + + /* Convert linux PTE bits into HW equivalents */ + andi. r3,r30,0x1fe /* Get basic set of flags */ + xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */ + rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ + rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ + andc r0,r30,r0 /* r0 = pte & ~r0 */ + rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + + /* We eventually do the icache sync here (maybe inline that + * code rather than call a C function...) + */ +BEGIN_FTR_SECTION + mr r4,r30 + mr r5,r7 + bl .hash_page_do_lazy_icache +END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) + + /* At this point, r3 contains new PP bits, save them in + * place of "access" in the param area (sic) + */ + std r3,STK_PARM(r4)(r1) + + /* Get htab_hash_mask */ + ld r4,htab_hash_mask@got(2) + ld r27,0(r4) /* htab_hash_mask -> r27 */ + + /* Check if we may already be in the hashtable, in this case, we + * go to out-of-line code to try to modify the HPTE. We look for + * the bit at (1 >> (index + 32)) + */ + andi. r0,r31,_PAGE_HASHPTE + li r26,0 /* Default hidx */ + beq htab_insert_pte + ld r6,STK_PARM(r6)(r1) + ori r26,r6,0x8000 /* Load the hidx mask */ + ld r26,0(r26) + addi r5,r25,36 /* Check actual HPTE_SUB bit, this */ + rldcr. r0,r31,r5,0 /* must match pgtable.h definition */ + bne htab_modify_pte + +htab_insert_pte: + /* real page number in r5, PTE RPN value + index */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT + add r5,r5,r25 + sldi r5,r5,HW_PAGE_SHIFT + + /* Calculate primary group hash */ + and r0,r28,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,0 /* !bolted, !secondary */ + li r8,MMU_PAGE_4K /* page size */ +_GLOBAL(htab_call_hpte_insert1) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge htab_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- htab_pte_insert_failure + + /* Now try secondary slot */ + + /* real page number in r5, PTE RPN value + index */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT + add r5,r5,r25 + sldi r5,r5,HW_PAGE_SHIFT + + /* Calculate secondary group hash */ + andc r0,r27,r28 + rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,HPTE_V_SECONDARY /* !bolted, secondary */ + li r8,MMU_PAGE_4K /* page size */ +_GLOBAL(htab_call_hpte_insert2) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge+ htab_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- htab_pte_insert_failure + + /* Both are full, we need to evict something */ + mftb r0 + /* Pick a random group based on TB */ + andi. r0,r0,1 + mr r5,r28 + bne 2f + not r5,r5 +2: and r0,r5,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + /* Call ppc_md.hpte_remove */ +_GLOBAL(htab_call_hpte_remove) + bl . /* patched by htab_finish_init() */ + + /* Try all again */ + b htab_insert_pte + +htab_bail_ok: + li r3,0 + b htab_bail + +htab_pte_insert_ok: + /* Insert slot number & secondary bit in PTE second half, + * clear _PAGE_BUSY and set approriate HPTE slot bit + */ + ld r6,STK_PARM(r6)(r1) + li r0,_PAGE_BUSY + andc r30,r30,r0 + /* HPTE SUB bit */ + li r0,1 + subfic r5,r25,27 /* Must match bit position in */ + sld r0,r0,r5 /* pgtable.h */ + or r30,r30,r0 + /* hindx */ + sldi r5,r25,2 + sld r3,r3,r5 + li r4,0xf + sld r4,r4,r5 + andc r26,r26,r4 + or r26,r26,r3 + ori r5,r6,0x8000 + std r26,0(r5) + lwsync + std r30,0(r6) + li r3, 0 +htab_bail: + ld r25,STK_REG(r25)(r1) + ld r26,STK_REG(r26)(r1) + ld r27,STK_REG(r27)(r1) + ld r28,STK_REG(r28)(r1) + ld r29,STK_REG(r29)(r1) + ld r30,STK_REG(r30)(r1) + ld r31,STK_REG(r31)(r1) + addi r1,r1,STACKFRAMESIZE + ld r0,16(r1) + mtlr r0 + blr + +htab_modify_pte: + /* Keep PP bits in r4 and slot idx from the PTE around in r3 */ + mr r4,r3 + sldi r5,r25,2 + srd r3,r26,r5 + + /* Secondary group ? if yes, get a inverted hash value */ + mr r5,r28 + andi. r0,r3,0x8 /* page secondary ? */ + beq 1f + not r5,r5 +1: andi. r3,r3,0x7 /* extract idx alone */ + + /* Calculate proper slot value for ppc_md.hpte_updatepp */ + and r0,r5,r27 + rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + add r3,r0,r3 /* add slot idx */ + + /* Call ppc_md.hpte_updatepp */ + mr r5,r29 /* va */ + li r6,MMU_PAGE_4K /* page size */ + ld r7,STK_PARM(r8)(r1) /* get "local" param */ +_GLOBAL(htab_call_hpte_updatepp) + bl . /* patched by htab_finish_init() */ + + /* if we failed because typically the HPTE wasn't really here + * we try an insertion. + */ + cmpdi 0,r3,-1 + beq- htab_insert_pte + + /* Clear the BUSY bit and Write out the PTE */ + li r0,_PAGE_BUSY + andc r30,r30,r0 + ld r6,STK_PARM(r6)(r1) + std r30,0(r6) + li r3,0 + b htab_bail + +htab_wrong_access: + /* Bail out clearing reservation */ + stdcx. r31,0,r6 + li r3,1 + b htab_bail htab_pte_insert_failure: /* Bail out restoring old PTE */ ld r6,STK_PARM(r6)(r1) std r31,0(r6) li r3,-1 - b bail + b htab_bail + + +/***************************************************************************** + * * + * 64K SW & 64K HW in a 64K segment pages implementation * + * * + *****************************************************************************/ + +_GLOBAL(__hash_page_64K) + mflr r0 + std r0,16(r1) + stdu r1,-STACKFRAMESIZE(r1) + /* Save all params that we need after a function call */ + std r6,STK_PARM(r6)(r1) + std r8,STK_PARM(r8)(r1) + + /* Add _PAGE_PRESENT to access */ + ori r4,r4,_PAGE_PRESENT + + /* Save non-volatile registers. + * r31 will hold "old PTE" + * r30 is "new PTE" + * r29 is "va" + * r28 is a hash value + * r27 is hashtab mask (maybe dynamic patched instead ?) + */ + std r27,STK_REG(r27)(r1) + std r28,STK_REG(r28)(r1) + std r29,STK_REG(r29)(r1) + std r30,STK_REG(r30)(r1) + std r31,STK_REG(r31)(r1) + + /* Step 1: + * + * Check permissions, atomically mark the linux PTE busy + * and hashed. + */ +1: + ldarx r31,0,r6 + /* Check access rights (access & ~(pte_val(*ptep))) */ + andc. r0,r4,r31 + bne- ht64_wrong_access + /* Check if PTE is busy */ + andi. r0,r31,_PAGE_BUSY + /* If so, just bail out and refault if needed. Someone else + * is changing this PTE anyway and might hash it. + */ + bne- ht64_bail_ok + /* Prepare new PTE value (turn access RW into DIRTY, then + * add BUSY,HASHPTE and ACCESSED) + */ + rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ + or r30,r30,r31 + ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + /* Write the linux PTE atomically (setting busy) */ + stdcx. r30,0,r6 + bne- 1b + isync + + /* Step 2: + * + * Insert/Update the HPTE in the hash table. At this point, + * r4 (access) is re-useable, we use it for the new HPTE flags + */ + + /* Calc va and put it in r29 */ + rldicr r29,r5,28,63-28 + rldicl r3,r3,0,36 + or r29,r3,r29 + + /* Calculate hash value for primary slot and store it in r28 */ + rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */ + rldicl r0,r3,64-16,52 /* (ea >> 16) & 0xfff */ + xor r28,r5,r0 + + /* Convert linux PTE bits into HW equivalents */ + andi. r3,r30,0x1fe /* Get basic set of flags */ + xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */ + rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ + rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ + andc r0,r30,r0 /* r0 = pte & ~r0 */ + rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + + /* We eventually do the icache sync here (maybe inline that + * code rather than call a C function...) + */ +BEGIN_FTR_SECTION + mr r4,r30 + mr r5,r7 + bl .hash_page_do_lazy_icache +END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) + + /* At this point, r3 contains new PP bits, save them in + * place of "access" in the param area (sic) + */ + std r3,STK_PARM(r4)(r1) + + /* Get htab_hash_mask */ + ld r4,htab_hash_mask@got(2) + ld r27,0(r4) /* htab_hash_mask -> r27 */ + + /* Check if we may already be in the hashtable, in this case, we + * go to out-of-line code to try to modify the HPTE + */ + andi. r0,r31,_PAGE_HASHPTE + bne ht64_modify_pte + +ht64_insert_pte: + /* Clear hpte bits in new pte (we also clear BUSY btw) and + * add _PAGE_HASHPTE + */ + lis r0,_PAGE_HPTEFLAGS@h + ori r0,r0,_PAGE_HPTEFLAGS@l + andc r30,r30,r0 + ori r30,r30,_PAGE_HASHPTE + + /* Phyical address in r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT + + /* Calculate primary group hash */ + and r0,r28,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,0 /* !bolted, !secondary */ + li r8,MMU_PAGE_64K +_GLOBAL(ht64_call_hpte_insert1) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge ht64_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- ht64_pte_insert_failure + + /* Now try secondary slot */ + + /* Phyical address in r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT + + /* Calculate secondary group hash */ + andc r0,r27,r28 + rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,HPTE_V_SECONDARY /* !bolted, secondary */ + li r8,MMU_PAGE_64K +_GLOBAL(ht64_call_hpte_insert2) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge+ ht64_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- ht64_pte_insert_failure + + /* Both are full, we need to evict something */ + mftb r0 + /* Pick a random group based on TB */ + andi. r0,r0,1 + mr r5,r28 + bne 2f + not r5,r5 +2: and r0,r5,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + /* Call ppc_md.hpte_remove */ +_GLOBAL(ht64_call_hpte_remove) + bl . /* patched by htab_finish_init() */ + + /* Try all again */ + b ht64_insert_pte + +ht64_bail_ok: + li r3,0 + b ht64_bail + +ht64_pte_insert_ok: + /* Insert slot number & secondary bit in PTE */ + rldimi r30,r3,12,63-15 + + /* Write out the PTE with a normal write + * (maybe add eieio may be good still ?) + */ +ht64_write_out_pte: + ld r6,STK_PARM(r6)(r1) + std r30,0(r6) + li r3, 0 +ht64_bail: + ld r27,STK_REG(r27)(r1) + ld r28,STK_REG(r28)(r1) + ld r29,STK_REG(r29)(r1) + ld r30,STK_REG(r30)(r1) + ld r31,STK_REG(r31)(r1) + addi r1,r1,STACKFRAMESIZE + ld r0,16(r1) + mtlr r0 + blr + +ht64_modify_pte: + /* Keep PP bits in r4 and slot idx from the PTE around in r3 */ + mr r4,r3 + rlwinm r3,r31,32-12,29,31 + + /* Secondary group ? if yes, get a inverted hash value */ + mr r5,r28 + andi. r0,r31,_PAGE_F_SECOND + beq 1f + not r5,r5 +1: + /* Calculate proper slot value for ppc_md.hpte_updatepp */ + and r0,r5,r27 + rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + add r3,r0,r3 /* add slot idx */ + + /* Call ppc_md.hpte_updatepp */ + mr r5,r29 /* va */ + li r6,MMU_PAGE_64K + ld r7,STK_PARM(r8)(r1) /* get "local" param */ +_GLOBAL(ht64_call_hpte_updatepp) + bl . /* patched by htab_finish_init() */ + + /* if we failed because typically the HPTE wasn't really here + * we try an insertion. + */ + cmpdi 0,r3,-1 + beq- ht64_insert_pte + + /* Clear the BUSY bit and Write out the PTE */ + li r0,_PAGE_BUSY + andc r30,r30,r0 + b ht64_write_out_pte + +ht64_wrong_access: + /* Bail out clearing reservation */ + stdcx. r31,0,r6 + li r3,1 + b ht64_bail + +ht64_pte_insert_failure: + /* Bail out restoring old PTE */ + ld r6,STK_PARM(r6)(r1) + std r31,0(r6) + li r3,-1 + b ht64_bail + + +#endif /* CONFIG_PPC_64K_PAGES */ +/***************************************************************************** + * * + * Huge pages implementation is in hugetlbpage.c * + * * + *****************************************************************************/ diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 174d14576c28..d96bcfe4c6f6 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -9,6 +9,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#undef DEBUG_LOW + #include #include #include @@ -22,11 +25,84 @@ #include #include #include +#include + +#ifdef DEBUG_LOW +#define DBG_LOW(fmt...) udbg_printf(fmt) +#else +#define DBG_LOW(fmt...) +#endif #define HPTE_LOCK_BIT 3 static DEFINE_SPINLOCK(native_tlbie_lock); +static inline void __tlbie(unsigned long va, unsigned int psize) +{ + unsigned int penc; + + /* clear top 16 bits, non SLS segment */ + va &= ~(0xffffULL << 48); + + switch (psize) { + case MMU_PAGE_4K: + va &= ~0xffful; + asm volatile("tlbie %0,0" : : "r" (va) : "memory"); + break; + default: + penc = mmu_psize_defs[psize].penc; + va &= ~((1ul << mmu_psize_defs[psize].shift) - 1); + va |= (0x7f >> (8 - penc)) << 12; + asm volatile("tlbie %0,1" : : "r" (va) : "memory"); + break; + } +} + +static inline void __tlbiel(unsigned long va, unsigned int psize) +{ + unsigned int penc; + + /* clear top 16 bits, non SLS segment */ + va &= ~(0xffffULL << 48); + + switch (psize) { + case MMU_PAGE_4K: + va &= ~0xffful; + asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)" + : : "r"(va) : "memory"); + break; + default: + penc = mmu_psize_defs[psize].penc; + va &= ~((1ul << mmu_psize_defs[psize].shift) - 1); + va |= (0x7f >> (8 - penc)) << 12; + asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)" + : : "r"(va) : "memory"); + break; + } + +} + +static inline void tlbie(unsigned long va, int psize, int local) +{ + unsigned int use_local = local && cpu_has_feature(CPU_FTR_TLBIEL); + int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); + + if (use_local) + use_local = mmu_psize_defs[psize].tlbiel; + if (lock_tlbie && !use_local) + spin_lock(&native_tlbie_lock); + asm volatile("ptesync": : :"memory"); + if (use_local) { + __tlbiel(va, psize); + asm volatile("ptesync": : :"memory"); + } else { + __tlbie(va, psize); + asm volatile("eieio; tlbsync; ptesync": : :"memory"); + } + if (lock_tlbie && !use_local) + spin_unlock(&native_tlbie_lock); +} + static inline void native_lock_hpte(hpte_t *hptep) { unsigned long *word = &hptep->v; @@ -48,13 +124,19 @@ static inline void native_unlock_hpte(hpte_t *hptep) } long native_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, unsigned long vflags, - unsigned long rflags) + unsigned long pa, unsigned long rflags, + unsigned long vflags, int psize) { hpte_t *hptep = htab_address + hpte_group; unsigned long hpte_v, hpte_r; int i; + if (!(vflags & HPTE_V_BOLTED)) { + DBG_LOW(" insert(group=%lx, va=%016lx, pa=%016lx," + " rflags=%lx, vflags=%lx, psize=%d)\n", + hpte_group, va, pa, rflags, vflags, psize); + } + for (i = 0; i < HPTES_PER_GROUP; i++) { if (! (hptep->v & HPTE_V_VALID)) { /* retry with lock held */ @@ -70,10 +152,13 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va, if (i == HPTES_PER_GROUP) return -1; - hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; - if (vflags & HPTE_V_LARGE) - va &= ~(1UL << HPTE_V_AVPN_SHIFT); - hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags; + hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; + hpte_r = hpte_encode_r(pa, psize) | rflags; + + if (!(vflags & HPTE_V_BOLTED)) { + DBG_LOW(" i=%x hpte_v=%016lx, hpte_r=%016lx\n", + i, hpte_v, hpte_r); + } hptep->r = hpte_r; /* Guarantee the second dword is visible before the valid bit */ @@ -96,6 +181,8 @@ static long native_hpte_remove(unsigned long hpte_group) int slot_offset; unsigned long hpte_v; + DBG_LOW(" remove(group=%lx)\n", hpte_group); + /* pick a random entry to start at */ slot_offset = mftb() & 0x7; @@ -126,34 +213,51 @@ static long native_hpte_remove(unsigned long hpte_group) return i; } -static inline void set_pp_bit(unsigned long pp, hpte_t *addr) +static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, + unsigned long va, int psize, int local) { - unsigned long old; - unsigned long *p = &addr->r; - - __asm__ __volatile__( - "1: ldarx %0,0,%3\n\ - rldimi %0,%2,0,61\n\ - stdcx. %0,0,%3\n\ - bne 1b" - : "=&r" (old), "=m" (*p) - : "r" (pp), "r" (p), "m" (*p) - : "cc"); + hpte_t *hptep = htab_address + slot; + unsigned long hpte_v, want_v; + int ret = 0; + + want_v = hpte_encode_v(va, psize); + + DBG_LOW(" update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)", + va, want_v & HPTE_V_AVPN, slot, newpp); + + native_lock_hpte(hptep); + + hpte_v = hptep->v; + + /* Even if we miss, we need to invalidate the TLB */ + if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { + DBG_LOW(" -> miss\n"); + native_unlock_hpte(hptep); + ret = -1; + } else { + DBG_LOW(" -> hit\n"); + /* Update the HPTE */ + hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | + (newpp & (HPTE_R_PP | HPTE_R_N)); + native_unlock_hpte(hptep); + } + + /* Ensure it is out of the tlb too. */ + tlbie(va, psize, local); + + return ret; } -/* - * Only works on small pages. Yes its ugly to have to check each slot in - * the group but we only use this during bootup. - */ -static long native_hpte_find(unsigned long vpn) +static long native_hpte_find(unsigned long va, int psize) { hpte_t *hptep; unsigned long hash; unsigned long i, j; long slot; - unsigned long hpte_v; + unsigned long want_v, hpte_v; - hash = hpt_hash(vpn, 0); + hash = hpt_hash(va, mmu_psize_defs[psize].shift); + want_v = hpte_encode_v(va, psize); for (j = 0; j < 2; j++) { slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; @@ -161,7 +265,7 @@ static long native_hpte_find(unsigned long vpn) hptep = htab_address + slot; hpte_v = hptep->v; - if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11)) + if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID) && ( !!(hpte_v & HPTE_V_SECONDARY) == j)) { /* HPTE matches */ @@ -177,120 +281,92 @@ static long native_hpte_find(unsigned long vpn) return -1; } -static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) -{ - hpte_t *hptep = htab_address + slot; - unsigned long hpte_v; - unsigned long avpn = va >> 23; - int ret = 0; - - if (large) - avpn &= ~1; - - native_lock_hpte(hptep); - - hpte_v = hptep->v; - - /* Even if we miss, we need to invalidate the TLB */ - if ((HPTE_V_AVPN_VAL(hpte_v) != avpn) - || !(hpte_v & HPTE_V_VALID)) { - native_unlock_hpte(hptep); - ret = -1; - } else { - set_pp_bit(newpp, hptep); - native_unlock_hpte(hptep); - } - - /* Ensure it is out of the tlb too */ - if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) { - tlbiel(va); - } else { - int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); - - if (lock_tlbie) - spin_lock(&native_tlbie_lock); - tlbie(va, large); - if (lock_tlbie) - spin_unlock(&native_tlbie_lock); - } - - return ret; -} - /* * Update the page protection bits. Intended to be used to create * guard pages for kernel data structures on pages which are bolted * in the HPT. Assumes pages being operated on will not be stolen. - * Does not work on large pages. * * No need to lock here because we should be the only user. */ -static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) +static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, + int psize) { - unsigned long vsid, va, vpn, flags = 0; + unsigned long vsid, va; long slot; hpte_t *hptep; - int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; - slot = native_hpte_find(vpn); + slot = native_hpte_find(va, psize); if (slot == -1) panic("could not find page to bolt\n"); hptep = htab_address + slot; - set_pp_bit(newpp, hptep); + /* Update the HPTE */ + hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | + (newpp & (HPTE_R_PP | HPTE_R_N)); - /* Ensure it is out of the tlb too */ - if (lock_tlbie) - spin_lock_irqsave(&native_tlbie_lock, flags); - tlbie(va, 0); - if (lock_tlbie) - spin_unlock_irqrestore(&native_tlbie_lock, flags); + /* Ensure it is out of the tlb too. */ + tlbie(va, psize, 0); } static void native_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) + int psize, int local) { hpte_t *hptep = htab_address + slot; unsigned long hpte_v; - unsigned long avpn = va >> 23; + unsigned long want_v; unsigned long flags; - int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); - - if (large) - avpn &= ~1; local_irq_save(flags); - native_lock_hpte(hptep); + DBG_LOW(" invalidate(va=%016lx, hash: %x)\n", va, slot); + + want_v = hpte_encode_v(va, psize); + native_lock_hpte(hptep); hpte_v = hptep->v; /* Even if we miss, we need to invalidate the TLB */ - if ((HPTE_V_AVPN_VAL(hpte_v) != avpn) - || !(hpte_v & HPTE_V_VALID)) { + if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) native_unlock_hpte(hptep); - } else { + else /* Invalidate the hpte. NOTE: this also unlocks it */ hptep->v = 0; - } - /* Invalidate the tlb */ - if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) { - tlbiel(va); - } else { - if (lock_tlbie) - spin_lock(&native_tlbie_lock); - tlbie(va, large); - if (lock_tlbie) - spin_unlock(&native_tlbie_lock); - } + /* Invalidate the TLB */ + tlbie(va, psize, local); + local_irq_restore(flags); } +/* + * XXX This need fixing based on page size. It's only used by + * native_hpte_clear() for now which needs fixing too so they + * make a good pair... + */ +static unsigned long slot2va(unsigned long hpte_v, unsigned long slot) +{ + unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v); + unsigned long va; + + va = avpn << 23; + + if (! (hpte_v & HPTE_V_LARGE)) { + unsigned long vpi, pteg; + + pteg = slot / HPTES_PER_GROUP; + if (hpte_v & HPTE_V_SECONDARY) + pteg = ~pteg; + + vpi = ((va >> 28) ^ pteg) & htab_hash_mask; + + va |= vpi << PAGE_SHIFT; + } + + return va; +} + /* * clear all mappings on kexec. All cpus are in real mode (or they will * be when they isi), and we are the only one left. We rely on our kernel @@ -298,6 +374,8 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, * * TODO: add batching support when enabled. remember, no dynamic memory here, * athough there is the control page available... + * + * XXX FIXME: 4k only for now ! */ static void native_hpte_clear(void) { @@ -327,7 +405,7 @@ static void native_hpte_clear(void) if (hpte_v & HPTE_V_VALID) { hptep->v = 0; - tlbie(slot2va(hpte_v, slot), hpte_v & HPTE_V_LARGE); + tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K, 0); } } @@ -335,59 +413,59 @@ static void native_hpte_clear(void) local_irq_restore(flags); } +/* + * Batched hash table flush, we batch the tlbie's to avoid taking/releasing + * the lock all the time + */ static void native_flush_hash_range(unsigned long number, int local) { - unsigned long va, vpn, hash, secondary, slot, flags, avpn; - int i, j; + unsigned long va, hash, index, hidx, shift, slot; hpte_t *hptep; unsigned long hpte_v; + unsigned long want_v; + unsigned long flags; + real_pte_t pte; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long large = batch->large; + unsigned long psize = batch->psize; + int i; local_irq_save(flags); - j = 0; for (i = 0; i < number; i++) { - va = batch->vaddr[j]; - if (large) - vpn = va >> HPAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - hash = hpt_hash(vpn, large); - secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15; - if (secondary) - hash = ~hash; - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12; - - hptep = htab_address + slot; - - avpn = va >> 23; - if (large) - avpn &= ~0x1UL; - - native_lock_hpte(hptep); - - hpte_v = hptep->v; - - /* Even if we miss, we need to invalidate the TLB */ - if ((HPTE_V_AVPN_VAL(hpte_v) != avpn) - || !(hpte_v & HPTE_V_VALID)) { - native_unlock_hpte(hptep); - } else { - /* Invalidate the hpte. NOTE: this also unlocks it */ - hptep->v = 0; - } - - j++; + va = batch->vaddr[i]; + pte = batch->pte[i]; + + pte_iterate_hashed_subpages(pte, psize, va, index, shift) { + hash = hpt_hash(va, shift); + hidx = __rpte_to_hidx(pte, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + hptep = htab_address + slot; + want_v = hpte_encode_v(va, psize); + native_lock_hpte(hptep); + hpte_v = hptep->v; + if (!HPTE_V_COMPARE(hpte_v, want_v) || + !(hpte_v & HPTE_V_VALID)) + native_unlock_hpte(hptep); + else + hptep->v = 0; + } pte_iterate_hashed_end(); } - if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) { + if (cpu_has_feature(CPU_FTR_TLBIEL) && + mmu_psize_defs[psize].tlbiel && local) { asm volatile("ptesync":::"memory"); - - for (i = 0; i < j; i++) - __tlbiel(batch->vaddr[i]); - + for (i = 0; i < number; i++) { + va = batch->vaddr[i]; + pte = batch->pte[i]; + + pte_iterate_hashed_subpages(pte, psize, va, index, + shift) { + __tlbiel(va, psize); + } pte_iterate_hashed_end(); + } asm volatile("ptesync":::"memory"); } else { int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); @@ -396,10 +474,15 @@ static void native_flush_hash_range(unsigned long number, int local) spin_lock(&native_tlbie_lock); asm volatile("ptesync":::"memory"); - - for (i = 0; i < j; i++) - __tlbie(batch->vaddr[i], large); - + for (i = 0; i < number; i++) { + va = batch->vaddr[i]; + pte = batch->pte[i]; + + pte_iterate_hashed_subpages(pte, psize, va, index, + shift) { + __tlbie(va, psize); + } pte_iterate_hashed_end(); + } asm volatile("eieio; tlbsync; ptesync":::"memory"); if (lock_tlbie) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 6e9e05cce02c..b2f3dbca6952 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -19,6 +19,7 @@ */ #undef DEBUG +#undef DEBUG_LOW #include #include @@ -59,6 +60,15 @@ #define DBG(fmt...) #endif +#ifdef DEBUG_LOW +#define DBG_LOW(fmt...) udbg_printf(fmt) +#else +#define DBG_LOW(fmt...) +#endif + +#define KB (1024) +#define MB (1024*KB) + /* * Note: pte --> Linux PTE * HPTE --> PowerPC Hashed Page Table Entry @@ -77,91 +87,290 @@ extern unsigned long dart_tablebase; hpte_t *htab_address; unsigned long htab_hash_mask; - unsigned long _SDR1; +struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; +int mmu_linear_psize = MMU_PAGE_4K; +int mmu_virtual_psize = MMU_PAGE_4K; +#ifdef CONFIG_HUGETLB_PAGE +int mmu_huge_psize = MMU_PAGE_16M; +unsigned int HPAGE_SHIFT; +#endif -#define KB (1024) -#define MB (1024*KB) - -static inline void loop_forever(void) -{ - volatile unsigned long x = 1; - for(;x;x|=1) - ; -} +/* There are definitions of page sizes arrays to be used when none + * is provided by the firmware. + */ -static inline void create_pte_mapping(unsigned long start, unsigned long end, - unsigned long mode, int large) +/* Pre-POWER4 CPUs (4k pages only) + */ +struct mmu_psize_def mmu_psize_defaults_old[] = { + [MMU_PAGE_4K] = { + .shift = 12, + .sllp = 0, + .penc = 0, + .avpnm = 0, + .tlbiel = 0, + }, +}; + +/* POWER4, GPUL, POWER5 + * + * Support for 16Mb large pages + */ +struct mmu_psize_def mmu_psize_defaults_gp[] = { + [MMU_PAGE_4K] = { + .shift = 12, + .sllp = 0, + .penc = 0, + .avpnm = 0, + .tlbiel = 1, + }, + [MMU_PAGE_16M] = { + .shift = 24, + .sllp = SLB_VSID_L, + .penc = 0, + .avpnm = 0x1UL, + .tlbiel = 0, + }, +}; + + +int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long mode, int psize) { - unsigned long addr; - unsigned int step; + unsigned long vaddr, paddr; + unsigned int step, shift; unsigned long tmp_mode; - unsigned long vflags; + int ret = 0; - if (large) { - step = 16*MB; - vflags = HPTE_V_BOLTED | HPTE_V_LARGE; - } else { - step = 4*KB; - vflags = HPTE_V_BOLTED; - } + shift = mmu_psize_defs[psize].shift; + step = 1 << shift; - for (addr = start; addr < end; addr += step) { + for (vaddr = vstart, paddr = pstart; vaddr < vend; + vaddr += step, paddr += step) { unsigned long vpn, hash, hpteg; - unsigned long vsid = get_kernel_vsid(addr); - unsigned long va = (vsid << 28) | (addr & 0xfffffff); - int ret = -1; - - if (large) - vpn = va >> HPAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - + unsigned long vsid = get_kernel_vsid(vaddr); + unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); + vpn = va >> shift; tmp_mode = mode; /* Make non-kernel text non-executable */ - if (!in_kernel_text(addr)) - tmp_mode = mode | HW_NO_EXEC; - - hash = hpt_hash(vpn, large); + if (!in_kernel_text(vaddr)) + tmp_mode = mode | HPTE_R_N; + hash = hpt_hash(va, shift); hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); + /* The crap below can be cleaned once ppd_md.probe() can + * set up the hash callbacks, thus we can just used the + * normal insert callback here. + */ #ifdef CONFIG_PPC_ISERIES - if (systemcfg->platform & PLATFORM_ISERIES_LPAR) - ret = iSeries_hpte_bolt_or_insert(hpteg, va, - virt_to_abs(addr) >> PAGE_SHIFT, - vflags, tmp_mode); + if (systemcfg->platform == PLATFORM_ISERIES_LPAR) + ret = iSeries_hpte_insert(hpteg, va, + virt_to_abs(paddr), + tmp_mode, + HPTE_V_BOLTED, + psize); else #endif #ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, - virt_to_abs(addr) >> PAGE_SHIFT, - vflags, tmp_mode); + virt_to_abs(paddr), + tmp_mode, + HPTE_V_BOLTED, + psize); else #endif #ifdef CONFIG_PPC_MULTIPLATFORM ret = native_hpte_insert(hpteg, va, - virt_to_abs(addr) >> PAGE_SHIFT, - vflags, tmp_mode); + virt_to_abs(paddr), + tmp_mode, HPTE_V_BOLTED, + psize); #endif + if (ret < 0) + break; + } + return ret < 0 ? ret : 0; +} - if (ret == -1) { - ppc64_terminate_msg(0x20, "create_pte_mapping"); - loop_forever(); +static int __init htab_dt_scan_page_sizes(unsigned long node, + const char *uname, int depth, + void *data) +{ + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + u32 *prop; + unsigned long size = 0; + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + prop = (u32 *)of_get_flat_dt_prop(node, + "ibm,segment-page-sizes", &size); + if (prop != NULL) { + DBG("Page sizes from device-tree:\n"); + size /= 4; + cur_cpu_spec->cpu_features &= ~(CPU_FTR_16M_PAGE); + while(size > 0) { + unsigned int shift = prop[0]; + unsigned int slbenc = prop[1]; + unsigned int lpnum = prop[2]; + unsigned int lpenc = 0; + struct mmu_psize_def *def; + int idx = -1; + + size -= 3; prop += 3; + while(size > 0 && lpnum) { + if (prop[0] == shift) + lpenc = prop[1]; + prop += 2; size -= 2; + lpnum--; + } + switch(shift) { + case 0xc: + idx = MMU_PAGE_4K; + break; + case 0x10: + idx = MMU_PAGE_64K; + break; + case 0x14: + idx = MMU_PAGE_1M; + break; + case 0x18: + idx = MMU_PAGE_16M; + cur_cpu_spec->cpu_features |= CPU_FTR_16M_PAGE; + break; + case 0x22: + idx = MMU_PAGE_16G; + break; + } + if (idx < 0) + continue; + def = &mmu_psize_defs[idx]; + def->shift = shift; + if (shift <= 23) + def->avpnm = 0; + else + def->avpnm = (1 << (shift - 23)) - 1; + def->sllp = slbenc; + def->penc = lpenc; + /* We don't know for sure what's up with tlbiel, so + * for now we only set it for 4K and 64K pages + */ + if (idx == MMU_PAGE_4K || idx == MMU_PAGE_64K) + def->tlbiel = 1; + else + def->tlbiel = 0; + + DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, " + "tlbiel=%d, penc=%d\n", + idx, shift, def->sllp, def->avpnm, def->tlbiel, + def->penc); } + return 1; + } + return 0; +} + + +static void __init htab_init_page_sizes(void) +{ + int rc; + + /* Default to 4K pages only */ + memcpy(mmu_psize_defs, mmu_psize_defaults_old, + sizeof(mmu_psize_defaults_old)); + + /* + * Try to find the available page sizes in the device-tree + */ + rc = of_scan_flat_dt(htab_dt_scan_page_sizes, NULL); + if (rc != 0) /* Found */ + goto found; + + /* + * Not in the device-tree, let's fallback on known size + * list for 16M capable GP & GR + */ + if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) && + cpu_has_feature(CPU_FTR_16M_PAGE)) + memcpy(mmu_psize_defs, mmu_psize_defaults_gp, + sizeof(mmu_psize_defaults_gp)); + found: + /* + * Pick a size for the linear mapping. Currently, we only support + * 16M, 1M and 4K which is the default + */ + if (mmu_psize_defs[MMU_PAGE_16M].shift) + mmu_linear_psize = MMU_PAGE_16M; + else if (mmu_psize_defs[MMU_PAGE_1M].shift) + mmu_linear_psize = MMU_PAGE_1M; + + /* + * Pick a size for the ordinary pages. Default is 4K, we support + * 64K if cache inhibited large pages are supported by the + * processor + */ +#ifdef CONFIG_PPC_64K_PAGES + if (mmu_psize_defs[MMU_PAGE_64K].shift && + cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) + mmu_virtual_psize = MMU_PAGE_64K; +#endif + + printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n", + mmu_psize_defs[mmu_linear_psize].shift, + mmu_psize_defs[mmu_virtual_psize].shift); + +#ifdef CONFIG_HUGETLB_PAGE + /* Init large page size. Currently, we pick 16M or 1M depending + * on what is available + */ + if (mmu_psize_defs[MMU_PAGE_16M].shift) + mmu_huge_psize = MMU_PAGE_16M; + else if (mmu_psize_defs[MMU_PAGE_1M].shift) + mmu_huge_psize = MMU_PAGE_1M; + + /* Calculate HPAGE_SHIFT and sanity check it */ + if (mmu_psize_defs[mmu_huge_psize].shift > 16 && + mmu_psize_defs[mmu_huge_psize].shift < 28) + HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift; + else + HPAGE_SHIFT = 0; /* No huge pages dude ! */ +#endif /* CONFIG_HUGETLB_PAGE */ +} + +static int __init htab_dt_scan_pftsize(unsigned long node, + const char *uname, int depth, + void *data) +{ + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + u32 *prop; + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL); + if (prop != NULL) { + /* pft_size[0] is the NUMA CEC cookie */ + ppc64_pft_size = prop[1]; + return 1; } + return 0; } -static unsigned long get_hashtable_size(void) +static unsigned long __init htab_get_table_size(void) { unsigned long rnd_mem_size, pteg_count; - /* If hash size wasn't obtained in prom.c, we calculate it now based on - * the total RAM size + /* If hash size isn't already provided by the platform, we try to + * retreive it from the device-tree. If it's not there neither, we + * calculate it now based on the total RAM size */ + if (ppc64_pft_size == 0) + of_scan_flat_dt(htab_dt_scan_pftsize, NULL); if (ppc64_pft_size) return 1UL << ppc64_pft_size; @@ -181,17 +390,21 @@ void __init htab_initialize(void) unsigned long table, htab_size_bytes; unsigned long pteg_count; unsigned long mode_rw; - int i, use_largepages = 0; unsigned long base = 0, size = 0; + int i; + extern unsigned long tce_alloc_start, tce_alloc_end; DBG(" -> htab_initialize()\n"); + /* Initialize page sizes */ + htab_init_page_sizes(); + /* * Calculate the required size of the htab. We want the number of * PTEGs to equal one half the number of real pages. */ - htab_size_bytes = get_hashtable_size(); + htab_size_bytes = htab_get_table_size(); pteg_count = htab_size_bytes >> 7; /* For debug, make the HTAB 1/8 as big as it normally would be. */ @@ -211,14 +424,11 @@ void __init htab_initialize(void) * the absolute address space. */ table = lmb_alloc(htab_size_bytes, htab_size_bytes); + BUG_ON(table == 0); DBG("Hash table allocated at %lx, size: %lx\n", table, htab_size_bytes); - if ( !table ) { - ppc64_terminate_msg(0x20, "hpt space"); - loop_forever(); - } htab_address = abs_to_virt(table); /* htab absolute addr + encoded htabsize */ @@ -234,8 +444,6 @@ void __init htab_initialize(void) * _NOT_ map it to avoid cache paradoxes as it's remapped non * cacheable later on */ - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - use_largepages = 1; /* create bolted the linear mapping in the hash table */ for (i=0; i < lmb.memory.cnt; i++) { @@ -246,27 +454,32 @@ void __init htab_initialize(void) #ifdef CONFIG_U3_DART /* Do not map the DART space. Fortunately, it will be aligned - * in such a way that it will not cross two lmb regions and will - * fit within a single 16Mb page. - * The DART space is assumed to be a full 16Mb region even if we - * only use 2Mb of that space. We will use more of it later for - * AGP GART. We have to use a full 16Mb large page. + * in such a way that it will not cross two lmb regions and + * will fit within a single 16Mb page. + * The DART space is assumed to be a full 16Mb region even if + * we only use 2Mb of that space. We will use more of it later + * for AGP GART. We have to use a full 16Mb large page. */ DBG("DART base: %lx\n", dart_tablebase); if (dart_tablebase != 0 && dart_tablebase >= base && dart_tablebase < (base + size)) { if (base != dart_tablebase) - create_pte_mapping(base, dart_tablebase, mode_rw, - use_largepages); + BUG_ON(htab_bolt_mapping(base, dart_tablebase, + base, mode_rw, + mmu_linear_psize)); if ((base + size) > (dart_tablebase + 16*MB)) - create_pte_mapping(dart_tablebase + 16*MB, base + size, - mode_rw, use_largepages); + BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, + base + size, + dart_tablebase+16*MB, + mode_rw, + mmu_linear_psize)); continue; } #endif /* CONFIG_U3_DART */ - create_pte_mapping(base, base + size, mode_rw, use_largepages); - } + BUG_ON(htab_bolt_mapping(base, base + size, base, + mode_rw, mmu_linear_psize)); + } /* * If we have a memory_limit and we've allocated TCEs then we need to @@ -282,8 +495,9 @@ void __init htab_initialize(void) if (base + size >= tce_alloc_start) tce_alloc_start = base + size + 1; - create_pte_mapping(tce_alloc_start, tce_alloc_end, - mode_rw, use_largepages); + BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, + tce_alloc_start, mode_rw, + mmu_linear_psize)); } DBG(" <- htab_initialize()\n"); @@ -298,9 +512,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) { struct page *page; - if (!pfn_valid(pte_pfn(pte))) - return pp; - page = pte_page(pte); /* page is dirty */ @@ -309,7 +520,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) __flush_dcache_icache(page_address(page)); set_bit(PG_arch_1, &page->flags); } else - pp |= HW_NO_EXEC; + pp |= HPTE_R_N; } return pp; } @@ -325,94 +536,169 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) unsigned long vsid; struct mm_struct *mm; pte_t *ptep; - int ret; - int user_region = 0; - int local = 0; cpumask_t tmp; + int rc, user_region = 0, local = 0; - if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) - return 1; + DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", + ea, access, trap); + if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) { + DBG_LOW(" out of pgtable range !\n"); + return 1; + } + + /* Get region & vsid */ switch (REGION_ID(ea)) { case USER_REGION_ID: user_region = 1; mm = current->mm; - if (! mm) + if (! mm) { + DBG_LOW(" user region with no mm !\n"); return 1; - + } vsid = get_vsid(mm->context.id, ea); break; case VMALLOC_REGION_ID: mm = &init_mm; vsid = get_kernel_vsid(ea); break; -#if 0 - case KERNEL_REGION_ID: - /* - * Should never get here - entire 0xC0... region is bolted. - * Send the problem up to do_page_fault - */ -#endif default: /* Not a valid range * Send the problem up to do_page_fault */ return 1; - break; } + DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid); + /* Get pgdir */ pgdir = mm->pgd; - if (pgdir == NULL) return 1; + /* Check CPU locality */ tmp = cpumask_of_cpu(smp_processor_id()); if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) local = 1; - /* Is this a huge page ? */ - if (unlikely(in_hugepage_area(mm->context, ea))) - ret = hash_huge_page(mm, access, ea, vsid, local); - else { - ptep = find_linux_pte(pgdir, ea); - if (ptep == NULL) - return 1; - ret = __hash_page(ea, access, vsid, ptep, trap, local); + /* Handle hugepage regions */ + if (unlikely(in_hugepage_area(mm->context, ea))) { + DBG_LOW(" -> huge page !\n"); + return hash_huge_page(mm, access, ea, vsid, local); + } + + /* Get PTE and page size from page tables */ + ptep = find_linux_pte(pgdir, ea); + if (ptep == NULL || !pte_present(*ptep)) { + DBG_LOW(" no PTE !\n"); + return 1; + } + +#ifndef CONFIG_PPC_64K_PAGES + DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); +#else + DBG_LOW(" i-pte: %016lx %016lx\n", pte_val(*ptep), + pte_val(*(ptep + PTRS_PER_PTE))); +#endif + /* Pre-check access permissions (will be re-checked atomically + * in __hash_page_XX but this pre-check is a fast path + */ + if (access & ~pte_val(*ptep)) { + DBG_LOW(" no access !\n"); + return 1; } - return ret; + /* Do actual hashing */ +#ifndef CONFIG_PPC_64K_PAGES + rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); +#else + if (mmu_virtual_psize == MMU_PAGE_64K) + rc = __hash_page_64K(ea, access, vsid, ptep, trap, local); + else + rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); +#endif /* CONFIG_PPC_64K_PAGES */ + +#ifndef CONFIG_PPC_64K_PAGES + DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep)); +#else + DBG_LOW(" o-pte: %016lx %016lx\n", pte_val(*ptep), + pte_val(*(ptep + PTRS_PER_PTE))); +#endif + DBG_LOW(" -> rc=%d\n", rc); + return rc; } -void flush_hash_page(unsigned long va, pte_t pte, int local) +void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap) { - unsigned long vpn, hash, secondary, slot; - unsigned long huge = pte_huge(pte); + unsigned long vsid; + void *pgdir; + pte_t *ptep; + cpumask_t mask; + unsigned long flags; + int local = 0; + + /* We don't want huge pages prefaulted for now + */ + if (unlikely(in_hugepage_area(mm->context, ea))) + return; + + DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx," + " trap=%lx\n", mm, mm->pgd, ea, access, trap); - if (huge) - vpn = va >> HPAGE_SHIFT; + /* Get PTE, VSID, access mask */ + pgdir = mm->pgd; + if (pgdir == NULL) + return; + ptep = find_linux_pte(pgdir, ea); + if (!ptep) + return; + vsid = get_vsid(mm->context.id, ea); + + /* Hash it in */ + local_irq_save(flags); + mask = cpumask_of_cpu(smp_processor_id()); + if (cpus_equal(mm->cpu_vm_mask, mask)) + local = 1; +#ifndef CONFIG_PPC_64K_PAGES + __hash_page_4K(ea, access, vsid, ptep, trap, local); +#else + if (mmu_virtual_psize == MMU_PAGE_64K) + __hash_page_64K(ea, access, vsid, ptep, trap, local); else - vpn = va >> PAGE_SHIFT; - hash = hpt_hash(vpn, huge); - secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15; - if (secondary) - hash = ~hash; - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12; - - ppc_md.hpte_invalidate(slot, va, huge, local); + __hash_page_4K(ea, access, vsid, ptep, trap, local); +#endif /* CONFIG_PPC_64K_PAGES */ + local_irq_restore(flags); +} + +void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local) +{ + unsigned long hash, index, shift, hidx, slot; + + DBG_LOW("flush_hash_page(va=%016x)\n", va); + pte_iterate_hashed_subpages(pte, psize, va, index, shift) { + hash = hpt_hash(va, shift); + hidx = __rpte_to_hidx(pte, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx); + ppc_md.hpte_invalidate(slot, va, psize, local); + } pte_iterate_hashed_end(); } void flush_hash_range(unsigned long number, int local) { - if (ppc_md.flush_hash_range) { + if (ppc_md.flush_hash_range) ppc_md.flush_hash_range(number, local); - } else { + else { int i; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); for (i = 0; i < number; i++) - flush_hash_page(batch->vaddr[i], batch->pte[i], local); + flush_hash_page(batch->vaddr[i], batch->pte[i], + batch->psize, local); } } @@ -452,6 +738,18 @@ void __init htab_finish_init(void) extern unsigned int *htab_call_hpte_remove; extern unsigned int *htab_call_hpte_updatepp; +#ifdef CONFIG_PPC_64K_PAGES + extern unsigned int *ht64_call_hpte_insert1; + extern unsigned int *ht64_call_hpte_insert2; + extern unsigned int *ht64_call_hpte_remove; + extern unsigned int *ht64_call_hpte_updatepp; + + make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert); + make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert); + make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove); + make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp); +#endif /* CONFIG_PPC_64K_PAGES */ + make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert); make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert); make_bl(htab_call_hpte_remove, ppc_md.hpte_remove); diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 0ea0994ed974..0073a04047e4 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -47,10 +47,25 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) pu = pud_offset(pg, addr); if (!pud_none(*pu)) { pm = pmd_offset(pu, addr); +#ifdef CONFIG_PPC_64K_PAGES + /* Currently, we use the normal PTE offset within full + * size PTE pages, thus our huge PTEs are scattered in + * the PTE page and we do waste some. We may change + * that in the future, but the current mecanism keeps + * things much simpler + */ + if (!pmd_none(*pm)) { + /* Note: pte_offset_* are all equivalent on + * ppc64 as we don't have HIGHMEM + */ + pt = pte_offset_kernel(pm, addr); + return pt; + } +#else /* CONFIG_PPC_64K_PAGES */ + /* On 4k pages, we put huge PTEs in the PMD page */ pt = (pte_t *)pm; - BUG_ON(!pmd_none(*pm) - && !(pte_present(*pt) && pte_huge(*pt))); return pt; +#endif /* CONFIG_PPC_64K_PAGES */ } } @@ -74,9 +89,16 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) if (pu) { pm = pmd_alloc(mm, pu, addr); if (pm) { +#ifdef CONFIG_PPC_64K_PAGES + /* See comment in huge_pte_offset. Note that if we ever + * want to put the page size in the PMD, we would have + * to open code our own pte_alloc* function in order + * to populate and set the size atomically + */ + pt = pte_alloc_map(mm, pm, addr); +#else /* CONFIG_PPC_64K_PAGES */ pt = (pte_t *)pm; - BUG_ON(!pmd_none(*pm) - && !(pte_present(*pt) && pte_huge(*pt))); +#endif /* CONFIG_PPC_64K_PAGES */ return pt; } } @@ -84,35 +106,29 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) return NULL; } -#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE) - void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { - int i; - if (pte_present(*ptep)) { - pte_clear(mm, addr, ptep); + /* We open-code pte_clear because we need to pass the right + * argument to hpte_update (huge / !huge) + */ + unsigned long old = pte_update(ptep, ~0UL); + if (old & _PAGE_HASHPTE) + hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); flush_tlb_pending(); } - - for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) { - *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); - ptep++; - } + *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); } pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { unsigned long old = pte_update(ptep, ~0UL); - int i; if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); - - for (i = 1; i < HUGEPTE_BATCH_SIZE; i++) - ptep[i] = __pte(0); + hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); + *ptep = __pte(0); return __pte(old); } @@ -563,6 +579,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, int lastshift; u16 areamask, curareas; + if (HPAGE_SHIFT == 0) + return -EINVAL; if (len & ~HPAGE_MASK) return -EINVAL; @@ -619,19 +637,15 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, unsigned long ea, unsigned long vsid, int local) { pte_t *ptep; - unsigned long va, vpn; - pte_t old_pte, new_pte; - unsigned long rflags, prpn; + unsigned long old_pte, new_pte; + unsigned long va, rflags, pa; long slot; int err = 1; - spin_lock(&mm->page_table_lock); - ptep = huge_pte_offset(mm, ea); /* Search the Linux page table for a match with va */ va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> HPAGE_SHIFT; /* * If no pte found or not present, send the problem up to @@ -640,8 +654,6 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, if (unlikely(!ptep || pte_none(*ptep))) goto out; -/* BUG_ON(pte_bad(*ptep)); */ - /* * Check the user's access rights to the page. If access should be * prevented then send the problem up to do_page_fault. @@ -661,58 +673,64 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, */ - old_pte = *ptep; - new_pte = old_pte; - - rflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW)); + do { + old_pte = pte_val(*ptep); + if (old_pte & _PAGE_BUSY) + goto out; + new_pte = old_pte | _PAGE_BUSY | + _PAGE_ACCESSED | _PAGE_HASHPTE; + } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, + old_pte, new_pte)); + + rflags = 0x2 | (!(new_pte & _PAGE_RW)); /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */ - rflags |= ((pte_val(new_pte) & _PAGE_EXEC) ? 0 : HW_NO_EXEC); + rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N); /* Check if pte already has an hpte (case 2) */ - if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) { + if (unlikely(old_pte & _PAGE_HASHPTE)) { /* There MIGHT be an HPTE for this pte */ unsigned long hash, slot; - hash = hpt_hash(vpn, 1); - if (pte_val(old_pte) & _PAGE_SECONDARY) + hash = hpt_hash(va, HPAGE_SHIFT); + if (old_pte & _PAGE_F_SECOND) hash = ~hash; slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12; + slot += (old_pte & _PAGE_F_GIX) >> 12; if (ppc_md.hpte_updatepp(slot, rflags, va, 1, local) == -1) - pte_val(old_pte) &= ~_PAGE_HPTEFLAGS; + old_pte &= ~_PAGE_HPTEFLAGS; } - if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) { - unsigned long hash = hpt_hash(vpn, 1); + if (likely(!(old_pte & _PAGE_HASHPTE))) { + unsigned long hash = hpt_hash(va, HPAGE_SHIFT); unsigned long hpte_group; - prpn = pte_pfn(old_pte); + pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT; repeat: hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - /* Update the linux pte with the HPTE slot */ - pte_val(new_pte) &= ~_PAGE_HPTEFLAGS; - pte_val(new_pte) |= _PAGE_HASHPTE; + /* clear HPTE slot informations in new PTE */ + new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; /* Add in WIMG bits */ /* XXX We should store these in the pte */ + /* --BenH: I think they are ... */ rflags |= _PAGE_COHERENT; - slot = ppc_md.hpte_insert(hpte_group, va, prpn, - HPTE_V_LARGE, rflags); + /* Insert into the hash table, primary slot */ + slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0, + mmu_huge_psize); /* Primary is full, try the secondary */ if (unlikely(slot == -1)) { - pte_val(new_pte) |= _PAGE_SECONDARY; + new_pte |= _PAGE_F_SECOND; hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, va, prpn, - HPTE_V_LARGE | + slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, HPTE_V_SECONDARY, - rflags); + mmu_huge_psize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * @@ -726,20 +744,18 @@ repeat: if (unlikely(slot == -2)) panic("hash_huge_page: pte_insert failed\n"); - pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX; - - /* - * No need to use ldarx/stdcx here because all who - * might be updating the pte will hold the - * page_table_lock - */ - *ptep = new_pte; + new_pte |= (slot << 12) & _PAGE_F_GIX; } + /* + * No need to use ldarx/stdcx here because all who + * might be updating the pte will hold the + * page_table_lock + */ + *ptep = __pte(new_pte & ~_PAGE_BUSY); + err = 0; out: - spin_unlock(&mm->page_table_lock); - return err; } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index b0fc822ec29f..dfe7fa37b41a 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -188,12 +188,21 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) memset(addr, 0, kmem_cache_size(cache)); } +#ifdef CONFIG_PPC_64K_PAGES +static const int pgtable_cache_size[2] = { + PTE_TABLE_SIZE, PGD_TABLE_SIZE +}; +static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { + "pte_pmd_cache", "pgd_cache", +}; +#else static const int pgtable_cache_size[2] = { PTE_TABLE_SIZE, PMD_TABLE_SIZE }; static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { "pgd_pte_cache", "pud_pmd_cache", }; +#endif /* CONFIG_PPC_64K_PAGES */ kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; @@ -201,19 +210,14 @@ void pgtable_cache_init(void) { int i; - BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]); - BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]); - BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]); - BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]); - for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) { int size = pgtable_cache_size[i]; const char *name = pgtable_cache_name[i]; pgtable_cache[i] = kmem_cache_create(name, size, size, - SLAB_HWCACHE_ALIGN - | SLAB_MUST_HWCACHE_ALIGN, + SLAB_HWCACHE_ALIGN | + SLAB_MUST_HWCACHE_ALIGN, zero_ctor, NULL); if (! pgtable_cache[i]) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 117b00012e14..7faa46b71f21 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -61,6 +61,9 @@ int init_bootmem_done; int mem_init_done; unsigned long memory_limit; +extern void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap); + /* * This is called by /dev/mem to know if a given address has to * be mapped non-cacheable or not @@ -493,18 +496,10 @@ EXPORT_SYMBOL(flush_icache_user_range); void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - /* handle i-cache coherency */ - unsigned long pfn = pte_pfn(pte); -#ifdef CONFIG_PPC32 - pmd_t *pmd; -#else - unsigned long vsid; - void *pgdir; - pte_t *ptep; - int local = 0; - cpumask_t tmp; - unsigned long flags; +#ifdef CONFIG_PPC_STD_MMU + unsigned long access = 0, trap; #endif + unsigned long pfn = pte_pfn(pte); /* handle i-cache coherency */ if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) && @@ -535,30 +530,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ if (!pte_young(pte) || address >= TASK_SIZE) return; -#ifdef CONFIG_PPC32 - if (Hash == 0) - return; - pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address); - if (!pmd_none(*pmd)) - add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd)); -#else - pgdir = vma->vm_mm->pgd; - if (pgdir == NULL) - return; - ptep = find_linux_pte(pgdir, address); - if (!ptep) + /* We try to figure out if we are coming from an instruction + * access fault and pass that down to __hash_page so we avoid + * double-faulting on execution of fresh text. We have to test + * for regs NULL since init will get here first thing at boot + * + * We also avoid filling the hash if not coming from a fault + */ + if (current->thread.regs == NULL) return; - - vsid = get_vsid(vma->vm_mm->context.id, address); - - local_irq_save(flags); - tmp = cpumask_of_cpu(smp_processor_id()); - if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) - local = 1; - - __hash_page(address, 0, vsid, ptep, 0x300, local); - local_irq_restore(flags); -#endif -#endif + trap = TRAP(current->thread.regs); + if (trap == 0x400) + access |= _PAGE_EXEC; + else if (trap != 0x300) + return; + hash_preload(vma->vm_mm, address, access, trap); +#endif /* CONFIG_PPC_STD_MMU */ } diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index b79a78206135..51b786940971 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -101,7 +101,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) pud_t *pudp; pmd_t *pmdp; pte_t *ptep; - unsigned long vsid; if (mem_init_done) { pgdp = pgd_offset_k(ea); @@ -117,28 +116,15 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); } else { - unsigned long va, vpn, hash, hpteg; - /* * If the mm subsystem is not fully up, we cannot create a * linux page table entry for this mapping. Simply bolt an * entry in the hardware page table. + * */ - vsid = get_kernel_vsid(ea); - va = (vsid << 28) | (ea & 0xFFFFFFF); - vpn = va >> PAGE_SHIFT; - - hash = hpt_hash(vpn, 0); - - hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); - - /* Panic if a pte grpup is full */ - if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT, - HPTE_V_BOLTED, - _PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX) - == -1) { - panic("map_io_page: could not insert mapping"); - } + if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, + mmu_virtual_psize)) + panic("Can't map bolted IO mapping"); } return 0; } diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index cef9e83cc7e9..d137abd241ff 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -178,6 +178,21 @@ void __init setbat(int index, unsigned long virt, unsigned long phys, bat_addrs[index].phys = phys; } +/* + * Preload a translation in the hash table + */ +void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap) +{ + pmd_t *pmd; + + if (Hash == 0) + return; + pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address); + if (!pmd_none(*pmd)) + add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd)); +} + /* * Initialize the hash table and patch the instructions in hashtable.S. */ diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 0473953f6a37..60e852f2f8e5 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -14,14 +14,32 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include #include #include #include +#include + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif -extern void slb_allocate(unsigned long ea); +extern void slb_allocate_realmode(unsigned long ea); +extern void slb_allocate_user(unsigned long ea); + +static void slb_allocate(unsigned long ea) +{ + /* Currently, we do real mode for all SLBs including user, but + * that will change if we bring back dynamic VSIDs + */ + slb_allocate_realmode(ea); +} static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot) { @@ -46,13 +64,15 @@ static void slb_flush_and_rebolt(void) { /* If you change this make sure you change SLB_NUM_BOLTED * appropriately too. */ - unsigned long ksp_flags = SLB_VSID_KERNEL; + unsigned long linear_llp, virtual_llp, lflags, vflags; unsigned long ksp_esid_data; WARN_ON(!irqs_disabled()); - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - ksp_flags |= SLB_VSID_L; + linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; + virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + lflags = SLB_VSID_KERNEL | linear_llp; + vflags = SLB_VSID_KERNEL | virtual_llp; ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); if ((ksp_esid_data & ESID_MASK) == KERNELBASE) @@ -67,9 +87,9 @@ static void slb_flush_and_rebolt(void) /* Slot 2 - kernel stack */ "slbmte %2,%3\n" "isync" - :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)), + :: "r"(mk_vsid_data(VMALLOCBASE, vflags)), "r"(mk_esid_data(VMALLOCBASE, 1)), - "r"(mk_vsid_data(ksp_esid_data, ksp_flags)), + "r"(mk_vsid_data(ksp_esid_data, lflags)), "r"(ksp_esid_data) : "memory"); } @@ -102,6 +122,9 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) get_paca()->slb_cache_ptr = 0; get_paca()->context = mm->context; +#ifdef CONFIG_PPC_64K_PAGES + get_paca()->pgdir = mm->pgd; +#endif /* CONFIG_PPC_64K_PAGES */ /* * preload some userspace segments into the SLB. @@ -131,28 +154,77 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) slb_allocate(unmapped_base); } +static inline void patch_slb_encoding(unsigned int *insn_addr, + unsigned int immed) +{ + /* Assume the instruction had a "0" immediate value, just + * "or" in the new value + */ + *insn_addr |= immed; + flush_icache_range((unsigned long)insn_addr, 4+ + (unsigned long)insn_addr); +} + void slb_initialize(void) { + unsigned long linear_llp, virtual_llp; + static int slb_encoding_inited; + extern unsigned int *slb_miss_kernel_load_linear; + extern unsigned int *slb_miss_kernel_load_virtual; + extern unsigned int *slb_miss_user_load_normal; +#ifdef CONFIG_HUGETLB_PAGE + extern unsigned int *slb_miss_user_load_huge; + unsigned long huge_llp; + + huge_llp = mmu_psize_defs[mmu_huge_psize].sllp; +#endif + + /* Prepare our SLB miss handler based on our page size */ + linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; + virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + if (!slb_encoding_inited) { + slb_encoding_inited = 1; + patch_slb_encoding(slb_miss_kernel_load_linear, + SLB_VSID_KERNEL | linear_llp); + patch_slb_encoding(slb_miss_kernel_load_virtual, + SLB_VSID_KERNEL | virtual_llp); + patch_slb_encoding(slb_miss_user_load_normal, + SLB_VSID_USER | virtual_llp); + + DBG("SLB: linear LLP = %04x\n", linear_llp); + DBG("SLB: virtual LLP = %04x\n", virtual_llp); +#ifdef CONFIG_HUGETLB_PAGE + patch_slb_encoding(slb_miss_user_load_huge, + SLB_VSID_USER | huge_llp); + DBG("SLB: huge LLP = %04x\n", huge_llp); +#endif + } + /* On iSeries the bolted entries have already been set up by * the hypervisor from the lparMap data in head.S */ #ifndef CONFIG_PPC_ISERIES - unsigned long flags = SLB_VSID_KERNEL; + { + unsigned long lflags, vflags; - /* Invalidate the entire SLB (even slot 0) & all the ERATS */ - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - flags |= SLB_VSID_L; + lflags = SLB_VSID_KERNEL | linear_llp; + vflags = SLB_VSID_KERNEL | virtual_llp; - asm volatile("isync":::"memory"); - asm volatile("slbmte %0,%0"::"r" (0) : "memory"); + /* Invalidate the entire SLB (even slot 0) & all the ERATS */ + asm volatile("isync":::"memory"); + asm volatile("slbmte %0,%0"::"r" (0) : "memory"); asm volatile("isync; slbia; isync":::"memory"); - create_slbe(KERNELBASE, flags, 0); - create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1); + create_slbe(KERNELBASE, lflags, 0); + + /* VMALLOC space has 4K pages always for now */ + create_slbe(VMALLOCBASE, vflags, 1); + /* We don't bolt the stack for the time being - we're in boot, * so the stack is in the bolted segment. By the time it goes * elsewhere, we'll call _switch() which will bolt in the new * one. */ asm volatile("isync":::"memory"); -#endif + } +#endif /* CONFIG_PPC_ISERIES */ get_paca()->stab_rr = SLB_NUM_BOLTED; } diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index a3a03da503bc..3e18241b6f35 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -18,61 +18,28 @@ #include #include -#include -#include #include #include #include +#include +#include +#include -/* void slb_allocate(unsigned long ea); +/* void slb_allocate_realmode(unsigned long ea); * * Create an SLB entry for the given EA (user or kernel). * r3 = faulting address, r13 = PACA * r9, r10, r11 are clobbered by this function * No other registers are examined or changed. */ -_GLOBAL(slb_allocate) - /* - * First find a slot, round robin. Previously we tried to find - * a free slot first but that took too long. Unfortunately we - * dont have any LRU information to help us choose a slot. - */ -#ifdef CONFIG_PPC_ISERIES - /* - * On iSeries, the "bolted" stack segment can be cast out on - * shared processor switch so we need to check for a miss on - * it and restore it to the right slot. - */ - ld r9,PACAKSAVE(r13) - clrrdi r9,r9,28 - clrrdi r11,r3,28 - li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */ - cmpld r9,r11 - beq 3f -#endif /* CONFIG_PPC_ISERIES */ - - ld r10,PACASTABRR(r13) - addi r10,r10,1 - /* use a cpu feature mask if we ever change our slb size */ - cmpldi r10,SLB_NUM_ENTRIES - - blt+ 4f - li r10,SLB_NUM_BOLTED - -4: - std r10,PACASTABRR(r13) -3: - /* r3 = faulting address, r10 = entry */ +_GLOBAL(slb_allocate_realmode) + /* r3 = faulting address */ srdi r9,r3,60 /* get region */ - srdi r3,r3,28 /* get esid */ + srdi r10,r3,28 /* get esid */ cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */ - rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */ - oris r10,r10,SLB_ESID_V@h /* r10 |= SLB_ESID_V */ - - /* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */ - + /* r3 = address, r10 = esid, cr7 = <>KERNELBASE */ blt cr7,0f /* user or kernel? */ /* kernel address: proto-VSID = ESID */ @@ -81,43 +48,161 @@ _GLOBAL(slb_allocate) * top segment. That's ok, the scramble below will translate * it to VSID 0, which is reserved as a bad VSID - one which * will never have any pages in it. */ - li r11,SLB_VSID_KERNEL -BEGIN_FTR_SECTION - bne cr7,9f - li r11,(SLB_VSID_KERNEL|SLB_VSID_L) -END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) - b 9f -0: /* user address: proto-VSID = context<<15 | ESID */ - srdi. r9,r3,USER_ESID_BITS + /* Check if hitting the linear mapping of the vmalloc/ioremap + * kernel space + */ + bne cr7,1f + + /* Linear mapping encoding bits, the "li" instruction below will + * be patched by the kernel at boot + */ +_GLOBAL(slb_miss_kernel_load_linear) + li r11,0 + b slb_finish_load + +1: /* vmalloc/ioremap mapping encoding bits, the "li" instruction below + * will be patched by the kernel at boot + */ +_GLOBAL(slb_miss_kernel_load_virtual) + li r11,0 + b slb_finish_load + + +0: /* user address: proto-VSID = context << 15 | ESID. First check + * if the address is within the boundaries of the user region + */ + srdi. r9,r10,USER_ESID_BITS bne- 8f /* invalid ea bits set */ + /* Figure out if the segment contains huge pages */ #ifdef CONFIG_HUGETLB_PAGE BEGIN_FTR_SECTION + b 1f +END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) lhz r9,PACAHIGHHTLBAREAS(r13) - srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT) + srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT) srd r9,r9,r11 lhz r11,PACALOWHTLBAREAS(r13) - srd r11,r11,r3 - or r9,r9,r11 -END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) + srd r11,r11,r10 + or. r9,r9,r11 + beq 1f +_GLOBAL(slb_miss_user_load_huge) + li r11,0 + b 2f +1: #endif /* CONFIG_HUGETLB_PAGE */ - li r11,SLB_VSID_USER +_GLOBAL(slb_miss_user_load_normal) + li r11,0 -#ifdef CONFIG_HUGETLB_PAGE -BEGIN_FTR_SECTION - rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */ -END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) -#endif /* CONFIG_HUGETLB_PAGE */ +2: + ld r9,PACACONTEXTID(r13) + rldimi r10,r9,USER_ESID_BITS,0 + b slb_finish_load + +8: /* invalid EA */ + li r10,0 /* BAD_VSID */ + li r11,SLB_VSID_USER /* flags don't much matter */ + b slb_finish_load + +#ifdef __DISABLED__ + +/* void slb_allocate_user(unsigned long ea); + * + * Create an SLB entry for the given EA (user or kernel). + * r3 = faulting address, r13 = PACA + * r9, r10, r11 are clobbered by this function + * No other registers are examined or changed. + * + * It is called with translation enabled in order to be able to walk the + * page tables. This is not currently used. + */ +_GLOBAL(slb_allocate_user) + /* r3 = faulting address */ + srdi r10,r3,28 /* get esid */ + + crset 4*cr7+lt /* set "user" flag for later */ + + /* check if we fit in the range covered by the pagetables*/ + srdi. r9,r3,PGTABLE_EADDR_SIZE + crnot 4*cr0+eq,4*cr0+eq + beqlr + /* now we need to get to the page tables in order to get the page + * size encoding from the PMD. In the future, we'll be able to deal + * with 1T segments too by getting the encoding from the PGD instead + */ + ld r9,PACAPGDIR(r13) + cmpldi cr0,r9,0 + beqlr + rlwinm r11,r10,8,25,28 + ldx r9,r9,r11 /* get pgd_t */ + cmpldi cr0,r9,0 + beqlr + rlwinm r11,r10,3,17,28 + ldx r9,r9,r11 /* get pmd_t */ + cmpldi cr0,r9,0 + beqlr + + /* build vsid flags */ + andi. r11,r9,SLB_VSID_LLP + ori r11,r11,SLB_VSID_USER + + /* get context to calculate proto-VSID */ ld r9,PACACONTEXTID(r13) - rldimi r3,r9,USER_ESID_BITS,0 + rldimi r10,r9,USER_ESID_BITS,0 + + /* fall through slb_finish_load */ + +#endif /* __DISABLED__ */ -9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */ - ASM_VSID_SCRAMBLE(r3,r9) - rldimi r11,r3,SLB_VSID_SHIFT,16 /* combine VSID and flags */ +/* + * Finish loading of an SLB entry and return + * + * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <>KERNELBASE + */ +slb_finish_load: + ASM_VSID_SCRAMBLE(r10,r9) + rldimi r11,r10,SLB_VSID_SHIFT,16 /* combine VSID and flags */ + + /* r3 = EA, r11 = VSID data */ + /* + * Find a slot, round robin. Previously we tried to find a + * free slot first but that took too long. Unfortunately we + * dont have any LRU information to help us choose a slot. + */ +#ifdef CONFIG_PPC_ISERIES + /* + * On iSeries, the "bolted" stack segment can be cast out on + * shared processor switch so we need to check for a miss on + * it and restore it to the right slot. + */ + ld r9,PACAKSAVE(r13) + clrrdi r9,r9,28 + clrrdi r3,r3,28 + li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */ + cmpld r9,r3 + beq 3f +#endif /* CONFIG_PPC_ISERIES */ + + ld r10,PACASTABRR(r13) + addi r10,r10,1 + /* use a cpu feature mask if we ever change our slb size */ + cmpldi r10,SLB_NUM_ENTRIES + + blt+ 4f + li r10,SLB_NUM_BOLTED + +4: + std r10,PACASTABRR(r13) + +3: + rldimi r3,r10,0,36 /* r3= EA[0:35] | entry */ + oris r10,r3,SLB_ESID_V@h /* r3 |= SLB_ESID_V */ + + /* r3 = ESID data, r11 = VSID data */ /* * No need for an isync before or after this slbmte. The exception @@ -125,7 +210,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) */ slbmte r11,r10 - bgelr cr7 /* we're done for kernel addresses */ + /* we're done for kernel addresses */ + crclr 4*cr0+eq /* set result to "success" */ + bgelr cr7 /* Update the slb cache */ lhz r3,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */ @@ -143,9 +230,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) li r3,SLB_CACHE_ENTRIES+1 2: sth r3,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */ + crclr 4*cr0+eq /* set result to "success" */ blr -8: /* invalid EA */ - li r3,0 /* BAD_VSID */ - li r11,SLB_VSID_USER /* flags don't much matter */ - b 9b diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 1b83f002bf27..fa325dbf98fc 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -26,7 +26,6 @@ struct stab_entry { unsigned long vsid_data; }; -/* Both the segment table and SLB code uses the following cache */ #define NR_STAB_CACHE_ENTRIES 8 DEFINE_PER_CPU(long, stab_cache_ptr); DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]); @@ -186,7 +185,7 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) /* Never flush the first entry. */ ste += 1; for (entry = 1; - entry < (PAGE_SIZE / sizeof(struct stab_entry)); + entry < (HW_PAGE_SIZE / sizeof(struct stab_entry)); entry++, ste++) { unsigned long ea; ea = ste->esid_data & ESID_MASK; @@ -200,6 +199,10 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) __get_cpu_var(stab_cache_ptr) = 0; +#ifdef CONFIG_PPC_64K_PAGES + get_paca()->pgdir = mm->pgd; +#endif /* CONFIG_PPC_64K_PAGES */ + /* Now preload some entries for the new task */ if (test_tsk_thread_flag(tsk, TIF_32BIT)) unmapped_base = TASK_UNMAPPED_BASE_USER32; @@ -223,8 +226,6 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) asm volatile("sync" : : : "memory"); } -extern void slb_initialize(void); - /* * Allocate segment tables for secondary CPUs. These must all go in * the first (bolted) segment, so that do_stab_bolted won't get a @@ -243,18 +244,21 @@ void stabs_alloc(void) if (cpu == 0) continue; /* stab for CPU 0 is statically allocated */ - newstab = lmb_alloc_base(PAGE_SIZE, PAGE_SIZE, 1< #include #include @@ -30,7 +31,7 @@ #include #include #include -#include +#include DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -126,28 +127,46 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) * (if we remove it we should clear the _PTE_HPTEFLAGS bits). */ void hpte_update(struct mm_struct *mm, unsigned long addr, - unsigned long pte, int wrprot) + pte_t *ptep, unsigned long pte, int huge) { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); unsigned long vsid; + unsigned int psize = mmu_virtual_psize; int i; i = batch->index; + /* We mask the address for the base page size. Huge pages will + * have applied their own masking already + */ + addr &= PAGE_MASK; + + /* Get page size (maybe move back to caller) */ + if (huge) { +#ifdef CONFIG_HUGETLB_PAGE + psize = mmu_huge_psize; +#else + BUG(); +#endif + } + /* * This can happen when we are in the middle of a TLB batch and * we encounter memory pressure (eg copy_page_range when it tries * to allocate a new pte). If we have to reclaim memory and end * up scanning and resetting referenced bits then our batch context * will change mid stream. + * + * We also need to ensure only one page size is present in a given + * batch */ - if (i != 0 && (mm != batch->mm || batch->large != pte_huge(pte))) { + if (i != 0 && (mm != batch->mm || batch->psize != psize)) { flush_tlb_pending(); i = 0; } if (i == 0) { batch->mm = mm; - batch->large = pte_huge(pte); + batch->psize = psize; } if (addr < KERNELBASE) { vsid = get_vsid(mm->context.id, addr); @@ -155,7 +174,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, } else vsid = get_kernel_vsid(addr); batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); - batch->pte[i] = __pte(pte); + batch->pte[i] = __real_pte(__pte(pte), ptep); batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) flush_tlb_pending(); @@ -177,7 +196,8 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) local = 1; if (i == 1) - flush_hash_page(batch->vaddr[0], batch->pte[0], local); + flush_hash_page(batch->vaddr[0], batch->pte[0], + batch->psize, local); else flush_hash_range(i, local); batch->index = 0; diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index b3c6c3374ca6..30bdcf3925d9 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c @@ -39,15 +39,16 @@ static inline void iSeries_hunlock(unsigned long slot) spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]); } -static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, unsigned long vflags, - unsigned long rflags) +long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, + unsigned long pa, unsigned long rflags, + unsigned long vflags, int psize) { - unsigned long arpn; long slot; hpte_t lhpte; int secondary = 0; + BUG_ON(psize != MMU_PAGE_4K); + /* * The hypervisor tries both primary and secondary. * If we are being called to insert in the secondary, @@ -59,8 +60,19 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, iSeries_hlock(hpte_group); - slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); - BUG_ON(lhpte.v & HPTE_V_VALID); + slot = HvCallHpt_findValid(&lhpte, va >> HW_PAGE_SHIFT); + if (unlikely(lhpte.v & HPTE_V_VALID)) { + if (vflags & HPTE_V_BOLTED) { + HvCallHpt_setSwBits(slot, 0x10, 0); + HvCallHpt_setPp(slot, PP_RWXX); + iSeries_hunlock(hpte_group); + if (slot < 0) + return 0x8 | (slot & 7); + else + return slot & 7; + } + BUG(); + } if (slot == -1) { /* No available entry found in either group */ iSeries_hunlock(hpte_group); @@ -73,10 +85,9 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, slot &= 0x7fffffffffffffff; } - arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT; - lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; - lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags; + lhpte.v = hpte_encode_v(va, MMU_PAGE_4K) | vflags | HPTE_V_VALID; + lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags; /* Now fill in the actual HPTE */ HvCallHpt_addValidate(slot, secondary, &lhpte); @@ -86,25 +97,6 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, return (secondary << 3) | (slot & 7); } -long iSeries_hpte_bolt_or_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, unsigned long vflags, - unsigned long rflags) -{ - long slot; - hpte_t lhpte; - - slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); - - if (lhpte.v & HPTE_V_VALID) { - /* Bolt the existing HPTE */ - HvCallHpt_setSwBits(slot, 0x10, 0); - HvCallHpt_setPp(slot, PP_RWXX); - return 0; - } - - return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags); -} - static unsigned long iSeries_hpte_getword0(unsigned long slot) { hpte_t hpte; @@ -150,15 +142,17 @@ static long iSeries_hpte_remove(unsigned long hpte_group) * bits 61..63 : PP2,PP1,PP0 */ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) + unsigned long va, int psize, int local) { hpte_t hpte; - unsigned long avpn = va >> 23; + unsigned long want_v; iSeries_hlock(slot); HvCallHpt_get(&hpte, slot); - if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) { + want_v = hpte_encode_v(va, MMU_PAGE_4K); + + if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) { /* * Hypervisor expects bits as NPPP, which is * different from how they are mapped in our PP. @@ -210,14 +204,17 @@ static long iSeries_hpte_find(unsigned long vpn) * * No need to lock here because we should be the only user. */ -static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) +static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, + int psize) { unsigned long vsid,va,vpn; long slot; + BUG_ON(psize != MMU_PAGE_4K); + vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; + vpn = va >> HW_PAGE_SHIFT; slot = iSeries_hpte_find(vpn); if (slot == -1) panic("updateboltedpp: Could not find page to bolt\n"); @@ -225,7 +222,7 @@ static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) } static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) + int psize, int local) { unsigned long hpte_v; unsigned long avpn = va >> 23; diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c index 62ec73479687..f476d71194fa 100644 --- a/arch/powerpc/platforms/iseries/hvlog.c +++ b/arch/powerpc/platforms/iseries/hvlog.c @@ -22,7 +22,7 @@ void HvCall_writeLogBuffer(const void *buffer, u64 len) while (len) { hv_buf.addr = cur; - left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; + left_this_page = ((cur & HW_PAGE_MASK) + HW_PAGE_SIZE) - cur; if (left_this_page > len) left_this_page = len; hv_buf.len = left_this_page; @@ -30,6 +30,6 @@ void HvCall_writeLogBuffer(const void *buffer, u64 len) HvCall2(HvCallBaseWriteLogBuffer, virt_to_abs(&hv_buf), left_this_page); - cur = (cur & PAGE_MASK) + PAGE_SIZE; + cur = (cur & HW_PAGE_MASK) + HW_PAGE_SIZE; } } diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 1a6845b5c5a4..bf081b345820 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -43,9 +43,12 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, u64 rc; union tce_entry tce; + index <<= TCE_PAGE_FACTOR; + npages <<= TCE_PAGE_FACTOR; + while (npages--) { tce.te_word = 0; - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; + tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT; if (tbl->it_type == TCE_VB) { /* Virtual Bus */ @@ -66,7 +69,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); index++; - uaddr += PAGE_SIZE; + uaddr += TCE_PAGE_SIZE; } } @@ -74,6 +77,9 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) { u64 rc; + npages <<= TCE_PAGE_FACTOR; + index <<= TCE_PAGE_FACTOR; + while (npages--) { rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0); if (rc) @@ -83,27 +89,6 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) } } -#ifdef CONFIG_PCI -/* - * This function compares the known tables to find an iommu_table - * that has already been built for hardware TCEs. - */ -static struct iommu_table *iommu_table_find(struct iommu_table * tbl) -{ - struct pci_dn *pdn; - - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - struct iommu_table *it = pdn->iommu_table; - if ((it != NULL) && - (it->it_type == TCE_PCI) && - (it->it_offset == tbl->it_offset) && - (it->it_index == tbl->it_index) && - (it->it_size == tbl->it_size)) - return it; - } - return NULL; -} - /* * Call Hv with the architected data structure to get TCE table info. * info. Put the returned data into the Linux representation of the @@ -113,8 +98,10 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) * 2. TCE table per Bus. * 3. TCE Table per IOA. */ -static void iommu_table_getparms(struct pci_dn *pdn, - struct iommu_table* tbl) +void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, + unsigned char virtbus, + struct iommu_table* tbl) { struct iommu_table_cb *parms; @@ -124,9 +111,9 @@ static void iommu_table_getparms(struct pci_dn *pdn, memset(parms, 0, sizeof(*parms)); - parms->itc_busno = pdn->busno; - parms->itc_slotno = pdn->LogicalSlot; - parms->itc_virtbus = 0; + parms->itc_busno = busno; + parms->itc_slotno = slotno; + parms->itc_virtbus = virtbus; HvCallXm_getTceTableParms(iseries_hv_addr(parms)); @@ -134,17 +121,40 @@ static void iommu_table_getparms(struct pci_dn *pdn, panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); /* itc_size is in pages worth of table, it_size is in # of entries */ - tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry); + tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / + sizeof(union tce_entry)) >> TCE_PAGE_FACTOR; tbl->it_busno = parms->itc_busno; - tbl->it_offset = parms->itc_offset; + tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; tbl->it_index = parms->itc_index; tbl->it_blocksize = 1; - tbl->it_type = TCE_PCI; + tbl->it_type = virtbus ? TCE_VB : TCE_PCI; kfree(parms); } +#ifdef CONFIG_PCI +/* + * This function compares the known tables to find an iommu_table + * that has already been built for hardware TCEs. + */ +static struct iommu_table *iommu_table_find(struct iommu_table * tbl) +{ + struct pci_dn *pdn; + + list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { + struct iommu_table *it = pdn->iommu_table; + if ((it != NULL) && + (it->it_type == TCE_PCI) && + (it->it_offset == tbl->it_offset) && + (it->it_index == tbl->it_index) && + (it->it_size == tbl->it_size)) + return it; + } + return NULL; +} + + void iommu_devnode_init_iSeries(struct device_node *dn) { struct iommu_table *tbl; @@ -152,7 +162,7 @@ void iommu_devnode_init_iSeries(struct device_node *dn) tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_getparms(pdn, tbl); + iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl); /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fda712b42168..c5207064977d 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -320,11 +320,11 @@ static void __init iSeries_init_early(void) */ if (naca.xRamDisk) { initrd_start = (unsigned long)__va(naca.xRamDisk); - initrd_end = initrd_start + naca.xRamDiskSize * PAGE_SIZE; + initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE; initrd_below_start_ok = 1; // ramdisk in kernel space ROOT_DEV = Root_RAM0; - if (((rd_size * 1024) / PAGE_SIZE) < naca.xRamDiskSize) - rd_size = (naca.xRamDiskSize * PAGE_SIZE) / 1024; + if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize) + rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024; } else #endif /* CONFIG_BLK_DEV_INITRD */ { @@ -470,13 +470,14 @@ static void __init build_iSeries_Memory_Map(void) */ hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress()); hptSizePages = (u32)HvCallHpt_getHptPages(); - hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT); + hptSizeChunks = hptSizePages >> + (MSCHUNKS_CHUNK_SHIFT - HW_PAGE_SHIFT); hptLastChunk = hptFirstChunk + hptSizeChunks - 1; printk("HPT absolute addr = %016lx, size = %dK\n", chunk_to_addr(hptFirstChunk), hptSizeChunks * 256); - ppc64_pft_size = __ilog2(hptSizePages * PAGE_SIZE); + ppc64_pft_size = __ilog2(hptSizePages * HW_PAGE_SIZE); /* * The actual hashed page table is in the hypervisor, @@ -629,7 +630,7 @@ static void __init iSeries_fixup_klimit(void) */ if (naca.xRamDisk) klimit = KERNELBASE + (u64)naca.xRamDisk + - (naca.xRamDiskSize * PAGE_SIZE); + (naca.xRamDiskSize * HW_PAGE_SIZE); else { /* * No ram disk was included - check and see if there diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index c27a66876c2c..384360ee06ec 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -30,41 +30,14 @@ static struct iommu_table vio_iommu_table; static void __init iommu_vio_init(void) { - struct iommu_table *t; - struct iommu_table_cb cb; - unsigned long cbp; - unsigned long itc_entries; + iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); + veth_iommu_table.it_size /= 2; + vio_iommu_table = veth_iommu_table; + vio_iommu_table.it_offset += veth_iommu_table.it_size; - cb.itc_busno = 255; /* Bus 255 is the virtual bus */ - cb.itc_virtbus = 0xff; /* Ask for virtual bus */ - - cbp = virt_to_abs(&cb); - HvCallXm_getTceTableParms(cbp); - - itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry); - veth_iommu_table.it_size = itc_entries / 2; - veth_iommu_table.it_busno = cb.itc_busno; - veth_iommu_table.it_offset = cb.itc_offset; - veth_iommu_table.it_index = cb.itc_index; - veth_iommu_table.it_type = TCE_VB; - veth_iommu_table.it_blocksize = 1; - - t = iommu_init_table(&veth_iommu_table); - - if (!t) + if (!iommu_init_table(&veth_iommu_table)) printk("Virtual Bus VETH TCE table failed.\n"); - - vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size; - vio_iommu_table.it_busno = cb.itc_busno; - vio_iommu_table.it_offset = cb.itc_offset + - veth_iommu_table.it_size; - vio_iommu_table.it_index = cb.itc_index; - vio_iommu_table.it_type = TCE_VB; - vio_iommu_table.it_blocksize = 1; - - t = iommu_init_table(&vio_iommu_table); - - if (!t) + if (!iommu_init_table(&vio_iommu_table)) printk("Virtual Bus VIO TCE table failed.\n"); } diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index fe97bfbf7463..842672695598 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -68,7 +68,8 @@ static DEFINE_SPINLOCK(statuslock); * For each kind of event we allocate a buffer that is * guaranteed not to cross a page boundary */ -static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned; +static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] + __attribute__((__aligned__(4096))); static atomic_t event_buffer_available[VIO_MAX_SUBTYPES]; static int event_buffer_initialised; @@ -116,12 +117,12 @@ static int proc_viopath_show(struct seq_file *m, void *v) HvLpEvent_Rc hvrc; DECLARE_MUTEX_LOCKED(Semaphore); - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + buf = kmalloc(HW_PAGE_SIZE, GFP_KERNEL); if (!buf) return 0; - memset(buf, 0, PAGE_SIZE); + memset(buf, 0, HW_PAGE_SIZE); - handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE, + handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, DMA_FROM_DEVICE); hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, @@ -131,7 +132,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) viopath_sourceinst(viopath_hostLp), viopath_targetinst(viopath_hostLp), (u64)(unsigned long)&Semaphore, VIOVERSION << 16, - ((u64)handle) << 32, PAGE_SIZE, 0, 0); + ((u64)handle) << 32, HW_PAGE_SIZE, 0, 0); if (hvrc != HvLpEvent_Rc_Good) printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc); @@ -140,7 +141,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) vlanMap = HvLpConfig_getVirtualLanIndexMap(); - buf[PAGE_SIZE-1] = '\0'; + buf[HW_PAGE_SIZE-1] = '\0'; seq_printf(m, "%s", buf); seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n", @@ -152,7 +153,8 @@ static int proc_viopath_show(struct seq_file *m, void *v) e2a(xItExtVpdPanel.systemSerial[4]), e2a(xItExtVpdPanel.systemSerial[5])); - dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE, + DMA_FROM_DEVICE); kfree(buf); return 0; diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index e384a5a91796..ab0c6dd6ec94 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define DEBUG +#undef DEBUG_LOW #include #include @@ -41,10 +41,10 @@ #include "plpar_wrappers.h" -#ifdef DEBUG -#define DBG(fmt...) udbg_printf(fmt) +#ifdef DEBUG_LOW +#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0) #else -#define DBG(fmt...) +#define DBG_LOW(fmt...) do { } while(0) #endif /* in pSeries_hvCall.S */ @@ -276,8 +276,9 @@ void vpa_init(int cpu) } long pSeries_lpar_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long vflags, unsigned long rflags) + unsigned long va, unsigned long pa, + unsigned long rflags, unsigned long vflags, + int psize) { unsigned long lpar_rc; unsigned long flags; @@ -285,11 +286,28 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long hpte_v, hpte_r; unsigned long dummy0, dummy1; - hpte_v = ((va >> 23) << HPTE_V_AVPN_SHIFT) | vflags | HPTE_V_VALID; - if (vflags & HPTE_V_LARGE) - hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT); - - hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags; + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " + "rflags=%lx, vflags=%lx, psize=%d)\n", + hpte_group, va, pa, rflags, vflags, psize); + + hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; + hpte_r = hpte_encode_r(pa, psize) | rflags; + + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); + +#if 1 + { + int i; + for (i=0;i<8;i++) { + unsigned long w0, w1; + plpar_pte_read(0, hpte_group, &w0, &w1); + BUG_ON (HPTE_V_COMPARE(hpte_v, w0) + && (w0 & HPTE_V_VALID)); + } + } +#endif /* Now fill in the actual HPTE */ /* Set CEC cookie to 0 */ @@ -299,23 +317,30 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, /* Exact = 0 */ flags = 0; - /* XXX why is this here? - Anton */ + /* Make pHyp happy */ if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) hpte_r &= ~_PAGE_COHERENT; lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v, hpte_r, &slot, &dummy0, &dummy1); - - if (unlikely(lpar_rc == H_PTEG_Full)) + if (unlikely(lpar_rc == H_PTEG_Full)) { + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" full\n"); return -1; + } /* * Since we try and ioremap PHBs we don't own, the pte insert * will fail. However we must catch the failure in hash_page * or we will loop forever, so return -2 in this case. */ - if (unlikely(lpar_rc != H_Success)) + if (unlikely(lpar_rc != H_Success)) { + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" lpar err %d\n", lpar_rc); return -2; + } + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" -> slot: %d\n", slot & 7); /* Because of iSeries, we have to pass down the secondary * bucket bit here as well @@ -340,10 +365,8 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group) /* don't remove a bolted entry */ lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset, (0x1UL << 4), &dummy1, &dummy2); - if (lpar_rc == H_Success) return i; - BUG_ON(lpar_rc != H_Not_Found); slot_offset++; @@ -371,20 +394,28 @@ static void pSeries_lpar_hptab_clear(void) * We can probably optimize here and assume the high bits of newpp are * already zero. For now I am paranoid. */ -static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) +static long pSeries_lpar_hpte_updatepp(unsigned long slot, + unsigned long newpp, + unsigned long va, + int psize, int local) { unsigned long lpar_rc; unsigned long flags = (newpp & 7) | H_AVPN; - unsigned long avpn = va >> 23; + unsigned long want_v; - if (large) - avpn &= ~0x1UL; + want_v = hpte_encode_v(va, psize); - lpar_rc = plpar_pte_protect(flags, slot, (avpn << 7)); + DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ", + want_v & HPTE_V_AVPN, slot, flags, psize); - if (lpar_rc == H_Not_Found) + lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN); + + if (lpar_rc == H_Not_Found) { + DBG_LOW("not found !\n"); return -1; + } + + DBG_LOW("ok\n"); BUG_ON(lpar_rc != H_Success); @@ -410,21 +441,22 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot) return dword0; } -static long pSeries_lpar_hpte_find(unsigned long vpn) +static long pSeries_lpar_hpte_find(unsigned long va, int psize) { unsigned long hash; unsigned long i, j; long slot; - unsigned long hpte_v; + unsigned long want_v, hpte_v; - hash = hpt_hash(vpn, 0); + hash = hpt_hash(va, mmu_psize_defs[psize].shift); + want_v = hpte_encode_v(va, psize); for (j = 0; j < 2; j++) { slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; for (i = 0; i < HPTES_PER_GROUP; i++) { hpte_v = pSeries_lpar_hpte_getword0(slot); - if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11)) + if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID) && (!!(hpte_v & HPTE_V_SECONDARY) == j)) { /* HPTE matches */ @@ -441,17 +473,15 @@ static long pSeries_lpar_hpte_find(unsigned long vpn) } static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, - unsigned long ea) + unsigned long ea, + int psize) { - unsigned long lpar_rc; - unsigned long vsid, va, vpn, flags; - long slot; + unsigned long lpar_rc, slot, vsid, va, flags; vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; - slot = pSeries_lpar_hpte_find(vpn); + slot = pSeries_lpar_hpte_find(va, psize); BUG_ON(slot == -1); flags = newpp & 7; @@ -461,18 +491,18 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, } static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) + int psize, int local) { - unsigned long avpn = va >> 23; + unsigned long want_v; unsigned long lpar_rc; unsigned long dummy1, dummy2; - if (large) - avpn &= ~0x1UL; - - lpar_rc = plpar_pte_remove(H_AVPN, slot, (avpn << 7), &dummy1, - &dummy2); + DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d", + slot, va, psize, local); + want_v = hpte_encode_v(va, psize); + lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN, + &dummy1, &dummy2); if (lpar_rc == H_Not_Found) return; @@ -494,7 +524,8 @@ void pSeries_lpar_flush_hash_range(unsigned long number, int local) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); for (i = 0; i < number; i++) - flush_hash_page(batch->vaddr[i], batch->pte[i], local); + flush_hash_page(batch->vaddr[i], batch->pte[i], + batch->psize, local); if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index b987164fca4c..2130cc315957 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -47,6 +47,10 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config PPC_STD_MMU + bool + default y + # We optimistically allocate largepages from the VM, so make the limit # large enough (16MB). This badly named config option is actually # max order + 1 @@ -294,6 +298,15 @@ config NODES_SPAN_OTHER_NODES def_bool y depends on NEED_MULTIPLE_NODES +config PPC_64K_PAGES + bool "64k page size" + help + This option changes the kernel logical page size to 64k. On machines + without processor support for 64k pages, the kernel will simulate + them by loading each individual 4k page on demand transparently, + while on hardware with such support, it will be used to map + normal application pages. + config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on SMP diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index 504dee836d29..bce9065da6cb 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c @@ -93,6 +93,9 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); +#ifdef CONFIG_PPC_64K_PAGES + DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); +#endif #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index db1cf397be2d..9e8050ea1225 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -195,11 +195,11 @@ exception_marker: #define EX_R12 24 #define EX_R13 32 #define EX_SRR0 40 -#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */ #define EX_DAR 48 -#define EX_LR 48 /* SLB miss saves LR, but not DAR */ #define EX_DSISR 56 #define EX_CCR 60 +#define EX_R3 64 +#define EX_LR 72 #define EXCEPTION_PROLOG_PSERIES(area, label) \ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ @@ -419,17 +419,22 @@ data_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_DAR std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_DAR - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x400, instruction_access) @@ -440,17 +445,22 @@ instruction_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) STD_EXCEPTION_PSERIES(0x600, alignment) @@ -508,6 +518,38 @@ _GLOBAL(do_stab_bolted_pSeries) mfspr r12,SPRN_SPRG2 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) +/* + * We have some room here we use that to put + * the peries slb miss user trampoline code so it's reasonably + * away from slb_miss_user_common to avoid problems with rfid + * + * This is used for when the SLB miss handler has to go virtual, + * which doesn't happen for now anymore but will once we re-implement + * dynamic VSIDs for shared page tables + */ +#ifdef __DISABLED__ +slb_miss_user_pseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + clrrdi r12,r13,32 + mfmsr r10 + mfspr r11,SRR0 /* save SRR0 */ + ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ + ori r10,r10,MSR_IR|MSR_DR|MSR_RI + mtspr SRR0,r12 + mfspr r12,SRR1 /* and SRR1 */ + mtspr SRR1,r10 + rfid + b . /* prevent spec. execution */ +#endif /* __DISABLED__ */ + /* * Vectors for the FWNMI option. Share common code. */ @@ -559,22 +601,59 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) .globl data_access_slb_iSeries data_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) mfspr r3,SPRN_DAR - b .do_slb_miss + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) .globl instruction_access_slb_iSeries instruction_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) - ld r3,PACALPPACA+LPPACASRR0(r13) - b .do_slb_miss + ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge .slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode + +#ifdef __DISABLED__ +slb_miss_user_iseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + EXCEPTION_PROLOG_ISERIES_2 + b slb_miss_user_common +#endif MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) @@ -809,6 +888,126 @@ instruction_access_common: li r5,0x400 b .do_hash_page /* Try to handle as hpte fault */ +/* + * Here is the common SLB miss user that is used when going to virtual + * mode for SLB misses, that is currently not used + */ +#ifdef __DISABLED__ + .align 7 + .globl slb_miss_user_common +slb_miss_user_common: + mflr r10 + std r3,PACA_EXGEN+EX_DAR(r13) + stw r9,PACA_EXGEN+EX_CCR(r13) + std r10,PACA_EXGEN+EX_LR(r13) + std r11,PACA_EXGEN+EX_SRR0(r13) + bl .slb_allocate_user + + ld r10,PACA_EXGEN+EX_LR(r13) + ld r3,PACA_EXGEN+EX_R3(r13) + lwz r9,PACA_EXGEN+EX_CCR(r13) + ld r11,PACA_EXGEN+EX_SRR0(r13) + mtlr r10 + beq- slb_miss_fault + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_user_slb + mfmsr r10 + +.machine push +.machine "power4" + mtcrf 0x80,r9 +.machine pop + + clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ + mtmsrd r10,1 + + mtspr SRR0,r11 + mtspr SRR1,r12 + + ld r9,PACA_EXGEN+EX_R9(r13) + ld r10,PACA_EXGEN+EX_R10(r13) + ld r11,PACA_EXGEN+EX_R11(r13) + ld r12,PACA_EXGEN+EX_R12(r13) + ld r13,PACA_EXGEN+EX_R13(r13) + rfid + b . + +slb_miss_fault: + EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) + ld r4,PACA_EXGEN+EX_DAR(r13) + li r5,0 + std r4,_DAR(r1) + std r5,_DSISR(r1) + b .handle_page_fault + +unrecov_user_slb: + EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + +#endif /* __DISABLED__ */ + + +/* + * r13 points to the PACA, r9 contains the saved CR, + * r12 contain the saved SRR1, SRR0 is still ready for return + * r3 has the faulting address + * r9 - r13 are saved in paca->exslb. + * r3 is saved in paca->slb_r3 + * We assume we aren't going to take any exceptions during this procedure. + */ +_GLOBAL(slb_miss_realmode) + mflr r10 + + stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ + std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ + + bl .slb_allocate_realmode + + /* All done -- return from exception. */ + + ld r10,PACA_EXSLB+EX_LR(r13) + ld r3,PACA_EXSLB+EX_R3(r13) + lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ +#ifdef CONFIG_PPC_ISERIES + ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ +#endif /* CONFIG_PPC_ISERIES */ + + mtlr r10 + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_slb + +.machine push +.machine "power4" + mtcrf 0x80,r9 + mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ +.machine pop + +#ifdef CONFIG_PPC_ISERIES + mtspr SPRN_SRR0,r11 + mtspr SPRN_SRR1,r12 +#endif /* CONFIG_PPC_ISERIES */ + ld r9,PACA_EXSLB+EX_R9(r13) + ld r10,PACA_EXSLB+EX_R10(r13) + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) + rfid + b . /* prevent speculative execution */ + +unrecov_slb: + EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + .align 7 .globl hardware_interrupt_common .globl hardware_interrupt_entry @@ -1138,62 +1337,6 @@ _GLOBAL(do_stab_bolted) rfid b . /* prevent speculative execution */ -/* - * r13 points to the PACA, r9 contains the saved CR, - * r11 and r12 contain the saved SRR0 and SRR1. - * r3 has the faulting address - * r9 - r13 are saved in paca->exslb. - * r3 is saved in paca->slb_r3 - * We assume we aren't going to take any exceptions during this procedure. - */ -_GLOBAL(do_slb_miss) - mflr r10 - - stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ - std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ - - bl .slb_allocate /* handle it */ - - /* All done -- return from exception. */ - - ld r10,PACA_EXSLB+EX_LR(r13) - ld r3,PACA_EXSLB+EX_R3(r13) - lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ -#ifdef CONFIG_PPC_ISERIES - ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ -#endif /* CONFIG_PPC_ISERIES */ - - mtlr r10 - - andi. r10,r12,MSR_RI /* check for unrecoverable exception */ - beq- unrecov_slb - -.machine push -.machine "power4" - mtcrf 0x80,r9 - mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ -.machine pop - -#ifdef CONFIG_PPC_ISERIES - mtspr SPRN_SRR0,r11 - mtspr SPRN_SRR1,r12 -#endif /* CONFIG_PPC_ISERIES */ - ld r9,PACA_EXSLB+EX_R9(r13) - ld r10,PACA_EXSLB+EX_R10(r13) - ld r11,PACA_EXSLB+EX_R11(r13) - ld r12,PACA_EXSLB+EX_R12(r13) - ld r13,PACA_EXSLB+EX_R13(r13) - rfid - b . /* prevent speculative execution */ - -unrecov_slb: - EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) - DISABLE_INTS - bl .save_nvgprs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl .unrecoverable_exception - b 1b - /* * Space for CPU0's segment table. * @@ -1569,7 +1712,10 @@ _GLOBAL(__secondary_start) #endif /* Initialize the first segment table (or SLB) entry */ ld r3,PACASTABVIRT(r13) /* get addr of segment table */ +BEGIN_FTR_SECTION bl .stab_initialize +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) + bl .slb_initialize /* Initialize the kernel stack. Just a repeat for iSeries. */ LOADADDR(r3,current_set) diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 5e27e5a6a35d..3133c72b28ec 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c @@ -23,7 +23,7 @@ static union { struct systemcfg data; u8 page[PAGE_SIZE]; -} systemcfg_store __page_aligned; +} systemcfg_store __attribute__((__section__(".data.page.aligned"))); struct systemcfg *systemcfg = &systemcfg_store.data; EXPORT_SYMBOL(systemcfg); diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 97bfceb5353b..dece31e58bc4 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -635,10 +635,10 @@ static inline char *find_flat_dt_string(u32 offset) * used to extract the memory informations at boot before we can * unflatten the tree */ -static int __init scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) { unsigned long p = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; @@ -695,8 +695,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node, * This function can be used within scan_flattened_dt callback to get * access to properties */ -static void* __init get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) { unsigned long p = node; @@ -996,7 +996,7 @@ void __init unflatten_device_tree(void) static int __init early_init_dt_scan_cpus(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); u32 *prop; unsigned long size; @@ -1004,17 +1004,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, if (type == NULL || strcmp(type, "cpu") != 0) return 0; - /* On LPAR, look for the first ibm,pft-size property for the hash table size - */ - if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) { - u32 *pft_size; - pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL); - if (pft_size != NULL) { - /* pft_size[0] is the NUMA CEC cookie */ - ppc64_pft_size = pft_size[1]; - } - } - if (initial_boot_params && initial_boot_params->version >= 2) { /* version 2 of the kexec param format adds the phys cpuid * of booted proc. @@ -1023,8 +1012,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, boot_cpuid = 0; } else { /* Check if it's the boot-cpu, set it's hw index in paca now */ - if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { - u32 *prop = get_flat_dt_prop(node, "reg", NULL); + if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) + != NULL) { + u32 *prop = of_get_flat_dt_prop(node, "reg", NULL); set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); boot_cpuid_phys = get_hard_smp_processor_id(0); } @@ -1032,14 +1022,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node, #ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); if (prop && (*prop) > 0) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } /* Same goes for Apple's "altivec" property */ - prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); if (prop) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; @@ -1051,7 +1041,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, * this by looking at the size of the ibm,ppc-interrupt-server#s * property */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &size); cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; if (prop && ((size / sizeof(u32)) > 1)) @@ -1072,26 +1062,26 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 0; /* get platform type */ - prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); if (prop == NULL) return 0; systemcfg->platform = *prop; /* check if iommu is forced on or off */ - if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) iommu_is_off = 1; - if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) iommu_force_on = 1; - prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL); + prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL); if (prop64) memory_limit = *prop64; - prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); + prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL); if (prop64) tce_alloc_start = *prop64; - prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); + prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); if (prop64) tce_alloc_end = *prop64; @@ -1102,9 +1092,12 @@ static int __init early_init_dt_scan_chosen(unsigned long node, { u64 *basep, *entryp; - basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL); - entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL); - prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL); + basep = (u64*)of_get_flat_dt_prop(node, + "linux,rtas-base", NULL); + entryp = (u64*)of_get_flat_dt_prop(node, + "linux,rtas-entry", NULL); + prop = (u32*)of_get_flat_dt_prop(node, + "linux,rtas-size", NULL); if (basep && entryp && prop) { rtas.base = *basep; rtas.entry = *entryp; @@ -1125,11 +1118,11 @@ static int __init early_init_dt_scan_root(unsigned long node, if (depth != 0) return 0; - prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL); dt_root_size_cells = (prop == NULL) ? 1 : *prop; DBG("dt_root_size_cells = %x\n", dt_root_size_cells); - prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL); dt_root_addr_cells = (prop == NULL) ? 2 : *prop; DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); @@ -1161,7 +1154,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); cell_t *reg, *endp; unsigned long l; @@ -1169,7 +1162,7 @@ static int __init early_init_dt_scan_memory(unsigned long node, if (type == NULL || strcmp(type, "memory") != 0) return 0; - reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); + reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); if (reg == NULL) return 0; @@ -1225,19 +1218,16 @@ void __init early_init_devtree(void *params) /* Setup flat device-tree pointer */ initial_boot_params = params; - /* By default, hash size is not set */ - ppc64_pft_size = 0; - /* Retreive various informations from the /chosen node of the * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... */ - scan_flat_dt(early_init_dt_scan_chosen, NULL); + of_scan_flat_dt(early_init_dt_scan_chosen, NULL); /* Scan memory nodes and rebuild LMBs */ lmb_init(); - scan_flat_dt(early_init_dt_scan_root, NULL); - scan_flat_dt(early_init_dt_scan_memory, NULL); + of_scan_flat_dt(early_init_dt_scan_root, NULL); + of_scan_flat_dt(early_init_dt_scan_memory, NULL); lmb_enforce_memory_limit(memory_limit); lmb_analyze(); systemcfg->physicalMemorySize = lmb_phys_mem_size(); @@ -1253,26 +1243,8 @@ void __init early_init_devtree(void *params) /* Retreive hash table size from flattened tree plus other * CPU related informations (altivec support, boot CPU ID, ...) */ - scan_flat_dt(early_init_dt_scan_cpus, NULL); - - /* If hash size wasn't obtained above, we calculate it now based on - * the total RAM size - */ - if (ppc64_pft_size == 0) { - unsigned long rnd_mem_size, pteg_count; - - /* round mem_size up to next power of 2 */ - rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); - if (rnd_mem_size < systemcfg->physicalMemorySize) - rnd_mem_size <<= 1; - - /* # pages / 2 */ - pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11); - - ppc64_pft_size = __ilog2(pteg_count << 7); - } + of_scan_flat_dt(early_init_dt_scan_cpus, NULL); - DBG("Hash pftSize: %x\n", (int)ppc64_pft_size); DBG(" <- early_init_devtree()\n"); } diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index c019501daceb..79a0556a0ab8 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -101,6 +101,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) +#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) #else /* ensure on 32b processors the flags are available for compiling but * don't do anything */ @@ -116,6 +117,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0) +#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) #endif #ifndef __ASSEMBLY__ @@ -339,6 +341,7 @@ enum { #ifdef __powerpc64__ CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL | + CPU_FTR_CI_LARGE_PAGE | #endif 0, diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 9d91bdd667ae..6a35e6570ccd 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -74,6 +74,11 @@ extern void iommu_devnode_init_pSeries(struct device_node *dn); /* Creates table for an individual device node */ extern void iommu_devnode_init_iSeries(struct device_node *dn); +/* Get table parameters from HV */ +extern void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, + unsigned char virtbus, + struct iommu_table* tbl); #endif /* CONFIG_PPC_ISERIES */ diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 629ca964b974..fa03864d06eb 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -47,20 +47,22 @@ struct machdep_calls { #ifdef CONFIG_PPC64 void (*hpte_invalidate)(unsigned long slot, unsigned long va, - int large, + int psize, int local); long (*hpte_updatepp)(unsigned long slot, unsigned long newpp, unsigned long va, - int large, + int pize, int local); void (*hpte_updateboltedpp)(unsigned long newpp, - unsigned long ea); + unsigned long ea, + int psize); long (*hpte_insert)(unsigned long hpte_group, unsigned long va, unsigned long prpn, + unsigned long rflags, unsigned long vflags, - unsigned long rflags); + int psize); long (*hpte_remove)(unsigned long hpte_group); void (*flush_hash_range)(unsigned long number, int local); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 3a0104fa0462..7587bf5f38c6 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -178,6 +178,14 @@ extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); +/* For scanning the flat device-tree at boot time */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); + /* For updating the device tree at runtime */ extern void of_attach_node(struct device_node *); extern void of_detach_node(const struct device_node *); diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index b5da0b851e02..3536a5cd7a2d 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -289,7 +289,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) #ifdef CONFIG_PPC64 static __inline__ unsigned long -__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new) +__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) { unsigned long prev; diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index ab17db79f69d..e525f49bd179 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h @@ -65,23 +65,27 @@ struct thread_info { /* thread information allocation */ -#ifdef CONFIG_DEBUG_STACK_USAGE -#define THREAD_INFO_GFP GFP_KERNEL | __GFP_ZERO -#else -#define THREAD_INFO_GFP GFP_KERNEL -#endif - #if THREAD_SHIFT >= PAGE_SHIFT #define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT) +#ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ - ((struct thread_info *)__get_free_pages(THREAD_INFO_GFP, THREAD_ORDER)) + ((struct thread_info *)__get_free_pages(GFP_KERNEL | \ + __GFP_ZERO, THREAD_ORDER)) +#else +#define alloc_thread_info(tsk) \ + ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_ORDER)) +#endif #define free_thread_info(ti) free_pages((unsigned long)ti, THREAD_ORDER) #else /* THREAD_SHIFT < PAGE_SHIFT */ -#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, THREAD_INFO_GFP) +#ifdef CONFIG_DEBUG_STACK_USAGE +#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL) +#else +#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) +#endif #define free_thread_info(ti) kfree(ti) #endif /* THREAD_SHIFT < PAGE_SHIFT */ diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index ca3655672bbc..a2998eee37bb 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h @@ -31,9 +31,9 @@ struct mm_struct; struct ppc64_tlb_batch { unsigned long index; struct mm_struct *mm; - pte_t pte[PPC64_TLB_BATCH_NR]; + real_pte_t pte[PPC64_TLB_BATCH_NR]; unsigned long vaddr[PPC64_TLB_BATCH_NR]; - unsigned int large; + unsigned int psize; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -48,8 +48,9 @@ static inline void flush_tlb_pending(void) put_cpu_var(ppc64_tlb_batch); } -extern void flush_hash_page(unsigned long va, pte_t pte, int local); -void flush_hash_range(unsigned long number, int local); +extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize, + int local); +extern void flush_hash_range(unsigned long number, int local); #else /* CONFIG_PPC64 */ diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index e0505acb77d9..4c18a5cb69f5 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h @@ -48,13 +48,21 @@ extern char initial_stab[]; /* Bits in the SLB VSID word */ #define SLB_VSID_SHIFT 12 +#define SLB_VSID_B ASM_CONST(0xc000000000000000) +#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) +#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) #define SLB_VSID_KS ASM_CONST(0x0000000000000800) #define SLB_VSID_KP ASM_CONST(0x0000000000000400) #define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ -#define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage */ +#define SLB_VSID_L ASM_CONST(0x0000000000000100) #define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ -#define SLB_VSID_LS ASM_CONST(0x0000000000000070) /* size of largepage */ - +#define SLB_VSID_LP ASM_CONST(0x0000000000000030) +#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) +#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) +#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) +#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) +#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) + #define SLB_VSID_KERNEL (SLB_VSID_KP) #define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) @@ -69,6 +77,7 @@ extern char initial_stab[]; #define HPTE_V_AVPN_SHIFT 7 #define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80) #define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) +#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN)) #define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) #define HPTE_V_LOCK ASM_CONST(0x0000000000000008) #define HPTE_V_LARGE ASM_CONST(0x0000000000000004) @@ -81,6 +90,7 @@ extern char initial_stab[]; #define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000) #define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) #define HPTE_R_PP ASM_CONST(0x0000000000000003) +#define HPTE_R_N ASM_CONST(0x0000000000000004) /* Values for PP (assumes Ks=0, Kp=1) */ /* pp0 will always be 0 for linux */ @@ -99,100 +109,120 @@ typedef struct { extern hpte_t *htab_address; extern unsigned long htab_hash_mask; -static inline unsigned long hpt_hash(unsigned long vpn, int large) +/* + * Page size definition + * + * shift : is the "PAGE_SHIFT" value for that page size + * sllp : is a bit mask with the value of SLB L || LP to be or'ed + * directly to a slbmte "vsid" value + * penc : is the HPTE encoding mask for the "LP" field: + * + */ +struct mmu_psize_def { - unsigned long vsid; - unsigned long page; - - if (large) { - vsid = vpn >> 4; - page = vpn & 0xf; - } else { - vsid = vpn >> 16; - page = vpn & 0xffff; - } + unsigned int shift; /* number of bits */ + unsigned int penc; /* HPTE encoding */ + unsigned int tlbiel; /* tlbiel supported for that page size */ + unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ + unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ +}; - return (vsid & 0x7fffffffffUL) ^ page; -} - -static inline void __tlbie(unsigned long va, int large) -{ - /* clear top 16 bits, non SLS segment */ - va &= ~(0xffffULL << 48); - - if (large) { - va &= HPAGE_MASK; - asm volatile("tlbie %0,1" : : "r"(va) : "memory"); - } else { - va &= PAGE_MASK; - asm volatile("tlbie %0,0" : : "r"(va) : "memory"); - } -} +#endif /* __ASSEMBLY__ */ -static inline void tlbie(unsigned long va, int large) -{ - asm volatile("ptesync": : :"memory"); - __tlbie(va, large); - asm volatile("eieio; tlbsync; ptesync": : :"memory"); -} +/* + * The kernel use the constants below to index in the page sizes array. + * The use of fixed constants for this purpose is better for performances + * of the low level hash refill handlers. + * + * A non supported page size has a "shift" field set to 0 + * + * Any new page size being implemented can get a new entry in here. Whether + * the kernel will use it or not is a different matter though. The actual page + * size used by hugetlbfs is not defined here and may be made variable + */ -static inline void __tlbiel(unsigned long va) -{ - /* clear top 16 bits, non SLS segment */ - va &= ~(0xffffULL << 48); - va &= PAGE_MASK; - - /* - * Thanks to Alan Modra we are now able to use machine specific - * assembly instructions (like tlbiel) by using the gas -many flag. - * However we have to support older toolchains so for the moment - * we hardwire it. - */ -#if 0 - asm volatile("tlbiel %0" : : "r"(va) : "memory"); -#else - asm volatile(".long 0x7c000224 | (%0 << 11)" : : "r"(va) : "memory"); -#endif -} +#define MMU_PAGE_4K 0 /* 4K */ +#define MMU_PAGE_64K 1 /* 64K */ +#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ +#define MMU_PAGE_1M 3 /* 1M */ +#define MMU_PAGE_16M 4 /* 16M */ +#define MMU_PAGE_16G 5 /* 16G */ +#define MMU_PAGE_COUNT 6 -static inline void tlbiel(unsigned long va) -{ - asm volatile("ptesync": : :"memory"); - __tlbiel(va); - asm volatile("ptesync": : :"memory"); -} +#ifndef __ASSEMBLY__ -static inline unsigned long slot2va(unsigned long hpte_v, unsigned long slot) -{ - unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v); - unsigned long va; +/* + * The current system page sizes + */ +extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; +extern int mmu_linear_psize; +extern int mmu_virtual_psize; - va = avpn << 23; +#ifdef CONFIG_HUGETLB_PAGE +/* + * The page size index of the huge pages for use by hugetlbfs + */ +extern int mmu_huge_psize; - if (! (hpte_v & HPTE_V_LARGE)) { - unsigned long vpi, pteg; +#endif /* CONFIG_HUGETLB_PAGE */ - pteg = slot / HPTES_PER_GROUP; - if (hpte_v & HPTE_V_SECONDARY) - pteg = ~pteg; +/* + * This function sets the AVPN and L fields of the HPTE appropriately + * for the page size + */ +static inline unsigned long hpte_encode_v(unsigned long va, int psize) +{ + unsigned long v = + v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); + v <<= HPTE_V_AVPN_SHIFT; + if (psize != MMU_PAGE_4K) + v |= HPTE_V_LARGE; + return v; +} - vpi = ((va >> 28) ^ pteg) & htab_hash_mask; +/* + * This function sets the ARPN, and LP fields of the HPTE appropriately + * for the page size. We assume the pa is already "clean" that is properly + * aligned for the requested page size + */ +static inline unsigned long hpte_encode_r(unsigned long pa, int psize) +{ + unsigned long r; - va |= vpi << PAGE_SHIFT; + /* A 4K page needs no special encoding */ + if (psize == MMU_PAGE_4K) + return pa & HPTE_R_RPN; + else { + unsigned int penc = mmu_psize_defs[psize].penc; + unsigned int shift = mmu_psize_defs[psize].shift; + return (pa & ~((1ul << shift) - 1)) | (penc << 12); } - - return va; + return r; } /* - * Handle a fault by adding an HPTE. If the address can't be determined - * to be valid via Linux page tables, return 1. If handled return 0 + * This hashes a virtual address for a 256Mb segment only for now */ -extern int __hash_page(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - int local); + +static inline unsigned long hpt_hash(unsigned long va, unsigned int shift) +{ + return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift); +} + +extern int __hash_page_4K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +extern int __hash_page_64K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +struct mm_struct; +extern int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local); extern void htab_finish_init(void); +extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long mode, + int psize); extern void hpte_init_native(void); extern void hpte_init_lpar(void); @@ -200,17 +230,21 @@ extern void hpte_init_iSeries(void); extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, - unsigned long vflags, - unsigned long rflags); -extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, - unsigned long vflags, unsigned long rflags); + unsigned long rflags, + unsigned long vflags, int psize); + +extern long native_hpte_insert(unsigned long hpte_group, + unsigned long va, unsigned long prpn, + unsigned long rflags, + unsigned long vflags, int psize); -extern long iSeries_hpte_bolt_or_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long vflags, unsigned long rflags); +extern long iSeries_hpte_insert(unsigned long hpte_group, + unsigned long va, unsigned long prpn, + unsigned long rflags, + unsigned long vflags, int psize); extern void stabs_alloc(void); +extern void slb_initialize(void); #endif /* __ASSEMBLY__ */ diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index 820dd729b895..4f512e9fa6b8 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h @@ -16,8 +16,16 @@ * 2 of the License, or (at your option) any later version. */ -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +/* + * Getting into a kernel thread, there is no valid user segment, mark + * paca->pgdir NULL so that SLB miss on user addresses will fault + */ +static inline void enter_lazy_tlb(struct mm_struct *mm, + struct task_struct *tsk) { +#ifdef CONFIG_PPC_64K_PAGES + get_paca()->pgdir = NULL; +#endif /* CONFIG_PPC_64K_PAGES */ } #define NO_CONTEXT 0 @@ -40,8 +48,13 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, cpu_set(smp_processor_id(), next->cpu_vm_mask); /* No need to flush userspace segments if the mm doesnt change */ +#ifdef CONFIG_PPC_64K_PAGES + if (prev == next && get_paca()->pgdir == next->pgd) + return; +#else if (prev == next) return; +#endif /* CONFIG_PPC_64K_PAGES */ #ifdef CONFIG_ALTIVEC if (cpu_has_feature(CPU_FTR_ALTIVEC)) diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h index f68fe91debaf..bccacd6aa93a 100644 --- a/include/asm-ppc64/paca.h +++ b/include/asm-ppc64/paca.h @@ -72,10 +72,15 @@ struct paca_struct { /* * Now, starting in cacheline 2, the exception save areas */ - u64 exgen[8] __attribute__((aligned(0x80))); /* used for most interrupts/exceptions */ - u64 exmc[8]; /* used for machine checks */ - u64 exslb[8]; /* used for SLB/segment table misses - * on the linear mapping */ + /* used for most interrupts/exceptions */ + u64 exgen[10] __attribute__((aligned(0x80))); + u64 exmc[10]; /* used for machine checks */ + u64 exslb[10]; /* used for SLB/segment table misses + * on the linear mapping */ +#ifdef CONFIG_PPC_64K_PAGES + pgd_t *pgdir; +#endif /* CONFIG_PPC_64K_PAGES */ + mm_context_t context; u16 slb_cache[SLB_CACHE_ENTRIES]; u16 slb_cache_ptr; diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h index d404431f0a9a..82ce187e5be8 100644 --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h @@ -13,32 +13,59 @@ #include #include /* for ASM_CONST */ -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 -#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +/* + * We support either 4k or 64k software page size. When using 64k pages + * however, wether we are really supporting 64k pages in HW or not is + * irrelevant to those definitions. We always define HW_PAGE_SHIFT to 12 + * as use of 64k pages remains a linux kernel specific, every notion of + * page number shared with the firmware, TCEs, iommu, etc... still assumes + * a page size of 4096. + */ +#ifdef CONFIG_PPC_64K_PAGES +#define PAGE_SHIFT 16 +#else +#define PAGE_SHIFT 12 +#endif -#define SID_SHIFT 28 -#define SID_MASK 0xfffffffffUL -#define ESID_MASK 0xfffffffff0000000UL -#define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) +#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) -#define HPAGE_SHIFT 24 -#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) -#define HPAGE_MASK (~(HPAGE_SIZE - 1)) +/* HW_PAGE_SHIFT is always 4k pages */ +#define HW_PAGE_SHIFT 12 +#define HW_PAGE_SIZE (ASM_CONST(1) << HW_PAGE_SHIFT) +#define HW_PAGE_MASK (~(HW_PAGE_SIZE-1)) -#ifdef CONFIG_HUGETLB_PAGE +/* PAGE_FACTOR is the number of bits factor between PAGE_SHIFT and + * HW_PAGE_SHIFT, that is 4k pages + */ +#define PAGE_FACTOR (PAGE_SHIFT - HW_PAGE_SHIFT) + +/* Segment size */ +#define SID_SHIFT 28 +#define SID_MASK 0xfffffffffUL +#define ESID_MASK 0xfffffffff0000000UL +#define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) +/* Large pages size */ + +#ifndef __ASSEMBLY__ +extern unsigned int HPAGE_SHIFT; +#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) +#define HPAGE_MASK (~(HPAGE_SIZE - 1)) #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +#endif /* __ASSEMBLY__ */ + +#ifdef CONFIG_HUGETLB_PAGE + #define HTLB_AREA_SHIFT 40 #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) -#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ - - (1U << GET_ESID(addr))) & 0xffff) -#define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ - - (1U << GET_HTLB_AREA(addr))) & 0xffff) +#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ + - (1U << GET_ESID(addr))) & 0xffff) +#define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ + - (1U << GET_HTLB_AREA(addr))) & 0xffff) #define ARCH_HAS_HUGEPAGE_ONLY_RANGE #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE @@ -114,7 +141,25 @@ static __inline__ void clear_page(void *addr) : "ctr", "memory"); } -extern void copy_page(void *to, void *from); +extern void copy_4K_page(void *to, void *from); + +#ifdef CONFIG_PPC_64K_PAGES +static inline void copy_page(void *to, void *from) +{ + unsigned int i; + for (i=0; i < (1 << (PAGE_SHIFT - 12)); i++) { + copy_4K_page(to, from); + to += 4096; + from += 4096; + } +} +#else /* CONFIG_PPC_64K_PAGES */ +static inline void copy_page(void *to, void *from) +{ + copy_4K_page(to, from); +} +#endif /* CONFIG_PPC_64K_PAGES */ + struct page; extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p); @@ -124,43 +169,75 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag * These are used to make use of C type-checking. * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b. */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pud; } pud_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; +/* PTE level */ +typedef struct { unsigned long pte; } pte_t; #define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pud_val(x) ((x).pud) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - #define __pte(x) ((pte_t) { (x) }) + +/* 64k pages additionally define a bigger "real PTE" type that gathers + * the "second half" part of the PTE for pseudo 64k pages + */ +#ifdef CONFIG_PPC_64K_PAGES +typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; +#else +typedef struct { pte_t pte; } real_pte_t; +#endif + +/* PMD level */ +typedef struct { unsigned long pmd; } pmd_t; +#define pmd_val(x) ((x).pmd) #define __pmd(x) ((pmd_t) { (x) }) + +/* PUD level exusts only on 4k pages */ +#ifndef CONFIG_PPC_64K_PAGES +typedef struct { unsigned long pud; } pud_t; +#define pud_val(x) ((x).pud) #define __pud(x) ((pud_t) { (x) }) +#endif + +/* PGD level */ +typedef struct { unsigned long pgd; } pgd_t; +#define pgd_val(x) ((x).pgd) #define __pgd(x) ((pgd_t) { (x) }) + +/* Page protection bits */ +typedef struct { unsigned long pgprot; } pgprot_t; +#define pgprot_val(x) ((x).pgprot) #define __pgprot(x) ((pgprot_t) { (x) }) #else + /* * .. while these make it easier on the compiler */ -typedef unsigned long pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pud_t; -typedef unsigned long pgd_t; -typedef unsigned long pgprot_t; +typedef unsigned long pte_t; #define pte_val(x) (x) +#define __pte(x) (x) + +#ifdef CONFIG_PPC_64K_PAGES +typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; +#else +typedef unsigned long real_pte_t; +#endif + + +typedef unsigned long pmd_t; #define pmd_val(x) (x) +#define __pmd(x) (x) + +#ifndef CONFIG_PPC_64K_PAGES +typedef unsigned long pud_t; #define pud_val(x) (x) +#define __pud(x) (x) +#endif + +typedef unsigned long pgd_t; #define pgd_val(x) (x) #define pgprot_val(x) (x) -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pud(x) (x) +typedef unsigned long pgprot_t; #define __pgd(x) (x) #define __pgprot(x) (x) diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h index 26bc49c1108d..98da0e4262bd 100644 --- a/include/asm-ppc64/pgalloc.h +++ b/include/asm-ppc64/pgalloc.h @@ -8,10 +8,16 @@ extern kmem_cache_t *pgtable_cache[]; +#ifdef CONFIG_PPC_64K_PAGES +#define PTE_CACHE_NUM 0 +#define PMD_CACHE_NUM 0 +#define PGD_CACHE_NUM 1 +#else #define PTE_CACHE_NUM 0 #define PMD_CACHE_NUM 1 #define PUD_CACHE_NUM 1 #define PGD_CACHE_NUM 0 +#endif /* * This program is free software; you can redistribute it and/or @@ -30,6 +36,8 @@ static inline void pgd_free(pgd_t *pgd) kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); } +#ifndef CONFIG_PPC_64K_PAGES + #define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) @@ -43,7 +51,30 @@ static inline void pud_free(pud_t *pud) kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); } -#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) +static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) +{ + pud_set(pud, (unsigned long)pmd); +} + +#define pmd_populate(mm, pmd, pte_page) \ + pmd_populate_kernel(mm, pmd, page_address(pte_page)) +#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte)) + + +#else /* CONFIG_PPC_64K_PAGES */ + +#define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd) + +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + pmd_set(pmd, (unsigned long)pte); +} + +#define pmd_populate(mm, pmd, pte_page) \ + pmd_populate_kernel(mm, pmd, page_address(pte_page)) + +#endif /* CONFIG_PPC_64K_PAGES */ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) { @@ -56,17 +87,15 @@ static inline void pmd_free(pmd_t *pmd) kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); } -#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte) -#define pmd_populate(mm, pmd, pte_page) \ - pmd_populate_kernel(mm, pmd, page_address(pte_page)) - -static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) { return kmem_cache_alloc(pgtable_cache[PTE_CACHE_NUM], GFP_KERNEL|__GFP_REPEAT); } -static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +static inline struct page *pte_alloc_one(struct mm_struct *mm, + unsigned long address) { return virt_to_page(pte_alloc_one_kernel(mm, address)); } @@ -103,7 +132,7 @@ static inline void pgtable_free(pgtable_free_t pgf) kmem_cache_free(pgtable_cache[cachenum], p); } -void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); +extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); #define __pte_free_tlb(tlb, ptepage) \ pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ @@ -111,9 +140,11 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); #define __pmd_free_tlb(tlb, pmd) \ pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) +#ifndef CONFIG_PPC_64K_PAGES #define __pud_free_tlb(tlb, pmd) \ pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) +#endif /* CONFIG_PPC_64K_PAGES */ #define check_pgt_cache() do { } while (0) diff --git a/include/asm-ppc64/pgtable-4k.h b/include/asm-ppc64/pgtable-4k.h new file mode 100644 index 000000000000..c883a2748558 --- /dev/null +++ b/include/asm-ppc64/pgtable-4k.h @@ -0,0 +1,88 @@ +/* + * Entries per page directory level. The PTE level must use a 64b record + * for each page table entry. The PMD and PGD level use a 32b record for + * each entry by assuming that each entry is page aligned. + */ +#define PTE_INDEX_SIZE 9 +#define PMD_INDEX_SIZE 7 +#define PUD_INDEX_SIZE 7 +#define PGD_INDEX_SIZE 9 + +#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE) +#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) +#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE) +#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) + +#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) +#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PUD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) + +/* PMD_SHIFT determines what a second-level page table entry can map */ +#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PUD_SHIFT determines what a third-level page table entry can map */ +#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) + +/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ +#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* PTE bits */ +#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ +#define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ +#define _PAGE_F_SECOND _PAGE_SECONDARY +#define _PAGE_F_GIX _PAGE_GROUP_IX + +/* PTE flags to conserve for HPTE identification */ +#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \ + _PAGE_SECONDARY | _PAGE_GROUP_IX) + +/* PAGE_MASK gives the right answer below, but only by accident */ +/* It should be preserving the high 48 bits and then specifically */ +/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \ + _PAGE_HPTEFLAGS) + +/* Bits to mask out from a PMD to get to the PTE page */ +#define PMD_MASKED_BITS 0 +/* Bits to mask out from a PUD to get to the PMD page */ +#define PUD_MASKED_BITS 0 +/* Bits to mask out from a PGD to get to the PUD page */ +#define PGD_MASKED_BITS 0 + +/* shift to put page number into pte */ +#define PTE_RPN_SHIFT (17) + +#define __real_pte(e,p) ((real_pte_t)(e)) +#define __rpte_to_pte(r) (r) +#define __rpte_to_hidx(r,index) (pte_val((r)) >> 12) + +#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ + do { \ + index = 0; \ + shift = mmu_psize_defs[psize].shift; \ + +#define pte_iterate_hashed_end() } while(0) + +/* + * 4-level page tables related bits + */ + +#define pgd_none(pgd) (!pgd_val(pgd)) +#define pgd_bad(pgd) (pgd_val(pgd) == 0) +#define pgd_present(pgd) (pgd_val(pgd) != 0) +#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) +#define pgd_page(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS) + +#define pud_offset(pgdp, addr) \ + (((pud_t *) pgd_page(*(pgdp))) + \ + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) + +#define pud_ERROR(e) \ + printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pud_val(e)) diff --git a/include/asm-ppc64/pgtable-64k.h b/include/asm-ppc64/pgtable-64k.h new file mode 100644 index 000000000000..c5f437c86b3c --- /dev/null +++ b/include/asm-ppc64/pgtable-64k.h @@ -0,0 +1,87 @@ +#include + + +#define PTE_INDEX_SIZE 12 +#define PMD_INDEX_SIZE 12 +#define PUD_INDEX_SIZE 0 +#define PGD_INDEX_SIZE 4 + +#define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE) +#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) +#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) + +#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) +#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) + +/* PMD_SHIFT determines what a second-level page table entry can map */ +#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* Additional PTE bits (don't change without checking asm in hash_low.S) */ +#define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */ +#define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */ +#define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ +#define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */ +#define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ + +/* PTE flags to conserve for HPTE identification */ +#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_HPTE_SUB |\ + _PAGE_COMBO) + +/* Shift to put page number into pte. + * + * That gives us a max RPN of 32 bits, which means a max of 48 bits + * of addressable physical space. + * We could get 3 more bits here by setting PTE_RPN_SHIFT to 29 but + * 32 makes PTEs more readable for debugging for now :) + */ +#define PTE_RPN_SHIFT (32) +#define PTE_RPN_MAX (1UL << (64 - PTE_RPN_SHIFT)) +#define PTE_RPN_MASK (~((1UL<> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) +#define __rpte_to_pte(r) ((r).pte) +#define __rpte_sub_valid(rpte, index) \ + (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index))) + + +/* Trick: we set __end to va + 64k, which happens works for + * a 16M page as well as we want only one iteration + */ +#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ + do { \ + unsigned long __end = va + PAGE_SIZE; \ + unsigned __split = (psize == MMU_PAGE_4K || \ + psize == MMU_PAGE_64K_AP); \ + shift = mmu_psize_defs[psize].shift; \ + for (index = 0; va < __end; index++, va += (1 << shift)) { \ + if (!__split || __rpte_sub_valid(rpte, index)) do { \ + +#define pte_iterate_hashed_end() } while(0); } } while(0) + + +#endif /* __ASSEMBLY__ */ diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index 8c3f574046b6..fde93ec36abc 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -15,40 +15,11 @@ #include #endif /* __ASSEMBLY__ */ -/* - * Entries per page directory level. The PTE level must use a 64b record - * for each page table entry. The PMD and PGD level use a 32b record for - * each entry by assuming that each entry is page aligned. - */ -#define PTE_INDEX_SIZE 9 -#define PMD_INDEX_SIZE 7 -#define PUD_INDEX_SIZE 7 -#define PGD_INDEX_SIZE 9 - -#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE) -#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) -#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE) -#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) - -#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) -#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) -#define PTRS_PER_PUD (1 << PMD_INDEX_SIZE) -#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) - -/* PMD_SHIFT determines what a second-level page table entry can map */ -#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) - -/* PUD_SHIFT determines what a third-level page table entry can map */ -#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) -#define PUD_SIZE (1UL << PUD_SHIFT) -#define PUD_MASK (~(PUD_SIZE-1)) - -/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ -#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#ifdef CONFIG_PPC_64K_PAGES +#include +#else +#include +#endif #define FIRST_USER_ADDRESS 0 @@ -75,8 +46,9 @@ #define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) /* - * Bits in a linux-style PTE. These match the bits in the - * (hardware-defined) PowerPC PTE as closely as possible. + * Common bits in a linux-style PTE. These match the bits in the + * (hardware-defined) PowerPC PTE as closely as possible. Additional + * bits may be defined in pgtable-*.h */ #define _PAGE_PRESENT 0x0001 /* software: pte contains a translation */ #define _PAGE_USER 0x0002 /* matches one of the PP bits */ @@ -91,15 +63,6 @@ #define _PAGE_RW 0x0200 /* software: user write access allowed */ #define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */ #define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */ -#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ -#define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ -#define _PAGE_HUGE 0x10000 /* 16MB page */ -/* Bits 0x7000 identify the index within an HPT Group */ -#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_SECONDARY | _PAGE_GROUP_IX) -/* PAGE_MASK gives the right answer below, but only by accident */ -/* It should be preserving the high 48 bits and then specifically */ -/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HPTEFLAGS) #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT) @@ -122,10 +85,10 @@ #define PAGE_AGP __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE) #define HAVE_PAGE_AGP -/* - * This bit in a hardware PTE indicates that the page is *not* executable. - */ -#define HW_NO_EXEC _PAGE_EXEC +/* PTEIDX nibble */ +#define _PTEIDX_SECONDARY 0x8 +#define _PTEIDX_GROUP_IX 0x7 + /* * POWER4 and newer have per page execute protection, older chips can only @@ -164,21 +127,10 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) #endif /* __ASSEMBLY__ */ -/* shift to put page number into pte */ -#define PTE_SHIFT (17) - #ifdef CONFIG_HUGETLB_PAGE -#ifndef __ASSEMBLY__ -int hash_huge_page(struct mm_struct *mm, unsigned long access, - unsigned long ea, unsigned long vsid, int local); -#endif /* __ASSEMBLY__ */ - #define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN -#else - -#define hash_huge_page(mm,a,ea,vsid,local) -1 #endif @@ -197,7 +149,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) pte_t pte; - pte_val(pte) = (pfn << PTE_SHIFT) | pgprot_val(pgprot); + pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot); return pte; } @@ -209,30 +161,25 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) /* pte_clear moved to later in this file */ -#define pte_pfn(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT))) +#define pte_pfn(x) ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT))) #define pte_page(x) pfn_to_page(pte_pfn(x)) -#define pmd_set(pmdp, ptep) ({BUG_ON((u64)ptep < KERNELBASE); pmd_val(*(pmdp)) = (unsigned long)(ptep);}) +#define pmd_set(pmdp, pmdval) (pmd_val(*(pmdp)) = (pmdval)) #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_bad(pmd) (pmd_val(pmd) == 0) #define pmd_present(pmd) (pmd_val(pmd) != 0) #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) -#define pmd_page_kernel(pmd) (pmd_val(pmd)) +#define pmd_page_kernel(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) -#define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (unsigned long)(pmdp)) +#define pud_set(pudp, pudval) (pud_val(*(pudp)) = (pudval)) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) ((pud_val(pud)) == 0) #define pud_present(pud) (pud_val(pud) != 0) #define pud_clear(pudp) (pud_val(*(pudp)) = 0) -#define pud_page(pud) (pud_val(pud)) +#define pud_page(pud) (pud_val(pud) & ~PUD_MASKED_BITS) #define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);}) -#define pgd_none(pgd) (!pgd_val(pgd)) -#define pgd_bad(pgd) (pgd_val(pgd) == 0) -#define pgd_present(pgd) (pgd_val(pgd) != 0) -#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) -#define pgd_page(pgd) (pgd_val(pgd)) /* * Find an entry in a page-table-directory. We combine the address region @@ -243,9 +190,6 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) -#define pud_offset(pgdp, addr) \ - (((pud_t *) pgd_page(*(pgdp))) + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) - #define pmd_offset(pudp,addr) \ (((pmd_t *) pud_page(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) @@ -271,7 +215,6 @@ static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC;} static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;} static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;} static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;} -static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE;} static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } @@ -286,7 +229,6 @@ static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(_PAGE_DIRTY); return pte; } static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } - static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } static inline pte_t pte_mkexec(pte_t pte) { @@ -298,7 +240,7 @@ static inline pte_t pte_mkdirty(pte_t pte) { static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } static inline pte_t pte_mkhuge(pte_t pte) { - pte_val(pte) |= _PAGE_HUGE; return pte; } + return pte; } /* Atomic PTE updates */ static inline unsigned long pte_update(pte_t *p, unsigned long clr) @@ -321,11 +263,13 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr) /* PTE updating functions, this function puts the PTE in the * batch, doesn't actually triggers the hash flush immediately, * you need to call flush_tlb_pending() to do that. + * Pass -1 for "normal" size (4K or 64K) */ -extern void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte, - int wrprot); +extern void hpte_update(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge); -static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline int __ptep_test_and_clear_young(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) { unsigned long old; @@ -333,7 +277,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned lon return 0; old = pte_update(ptep, _PAGE_ACCESSED); if (old & _PAGE_HASHPTE) { - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); flush_tlb_pending(); } return (old & _PAGE_ACCESSED) != 0; @@ -351,7 +295,8 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned lon * moment we always flush but we need to fix hpte_update and test if the * optimisation is worth it. */ -static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) { unsigned long old; @@ -359,7 +304,7 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned lon return 0; old = pte_update(ptep, _PAGE_DIRTY); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); return (old & _PAGE_DIRTY) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY @@ -371,7 +316,8 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned lon }) #define __HAVE_ARCH_PTEP_SET_WRPROTECT -static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) { unsigned long old; @@ -379,7 +325,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, return; old = pte_update(ptep, _PAGE_RW); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); } /* @@ -408,21 +354,23 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, }) #define __HAVE_ARCH_PTEP_GET_AND_CLEAR -static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) { unsigned long old = pte_update(ptep, ~0UL); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); return __pte(old); } -static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, + pte_t * ptep) { unsigned long old = pte_update(ptep, ~0UL); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); } /* @@ -435,7 +383,14 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_clear(mm, addr, ptep); flush_tlb_pending(); } - *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); + pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); + +#ifdef CONFIG_PPC_64K_PAGES + if (mmu_virtual_psize != MMU_PAGE_64K) + pte = __pte(pte_val(pte) | _PAGE_COMBO); +#endif /* CONFIG_PPC_64K_PAGES */ + + *ptep = pte; } /* Set the dirty and/or accessed bits atomically in a linux PTE, this @@ -482,8 +437,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -#define pud_ERROR(e) \ - printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) @@ -509,12 +462,12 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ #define __swp_type(entry) (((entry).val >> 1) & 0x3f) #define __swp_offset(entry) ((entry).val >> 8) -#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) -#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_SHIFT) -#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_SHIFT)|_PAGE_FILE}) -#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_SHIFT) +#define __swp_entry(type, offset) ((swp_entry_t){((type)<< 1)|((offset)<<8)}) +#define __pte_to_swp_entry(pte) ((swp_entry_t){pte_val(pte) >> PTE_RPN_SHIFT}) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_RPN_SHIFT }) +#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_RPN_SHIFT) +#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) +#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) /* * kern_addr_valid is intended to indicate whether an address is a valid @@ -532,29 +485,22 @@ void pgtable_cache_init(void); /* * find_linux_pte returns the address of a linux pte for a given * effective address and directory. If not found, it returns zero. - */ -static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) + */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) { pgd_t *pg; pud_t *pu; pmd_t *pm; pte_t *pt = NULL; - pte_t pte; pg = pgdir + pgd_index(ea); if (!pgd_none(*pg)) { pu = pud_offset(pg, ea); if (!pud_none(*pu)) { pm = pmd_offset(pu, ea); - if (pmd_present(*pm)) { + if (pmd_present(*pm)) pt = pte_offset_kernel(pm, ea); - pte = *pt; - if (!pte_present(pte)) - pt = NULL; - } } } - return pt; } diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index e8d0d2ab4c0f..bdb47174ff0e 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -188,6 +188,14 @@ extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); +/* For scanning the flat device-tree at boot time */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); + /* For updating the device tree at runtime */ extern void of_attach_node(struct device_node *); extern void of_detach_node(const struct device_node *); diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index 99b8ca52f101..0cdd66c9f4b7 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -248,7 +248,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) } static __inline__ unsigned long -__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new) +__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) { unsigned long prev; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index c9b43360fd33..9a565808da3f 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -103,6 +103,9 @@ static int __init hugetlb_init(void) unsigned long i; struct page *page; + if (HPAGE_SHIFT == 0) + return 0; + for (i = 0; i < MAX_NUMNODES; ++i) INIT_LIST_HEAD(&hugepage_freelists[i]); -- cgit v1.2.3 From ead837174d265b24334f0721a84cbdda8ccd89a7 Mon Sep 17 00:00:00 2001 From: John Rose Date: Fri, 4 Nov 2005 15:30:56 -0600 Subject: [PATCH] dlpar enable for OF pci probe This patch contains the arch/ppc64 bits for enabling DLPAR and PCI Hotplug for the new OF-based PCI probe mechanism. This code path is currently broken. Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/ppc64/kernel/pci.c | 17 +++++++++-------- arch/ppc64/kernel/rtas_pci.c | 6 +----- include/asm-powerpc/ppc-pci.h | 1 + include/asm-ppc64/pci.h | 8 ++++++++ 4 files changed, 19 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 3d2106b022a1..30247ff74972 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -295,8 +295,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) } } -static struct pci_dev *of_create_pci_dev(struct device_node *node, - struct pci_bus *bus, int devfn) +struct pci_dev *of_create_pci_dev(struct device_node *node, + struct pci_bus *bus, int devfn) { struct pci_dev *dev; const char *type; @@ -354,10 +354,9 @@ static struct pci_dev *of_create_pci_dev(struct device_node *node, return dev; } +EXPORT_SYMBOL(of_create_pci_dev); -static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev); - -static void __devinit of_scan_bus(struct device_node *node, +void __devinit of_scan_bus(struct device_node *node, struct pci_bus *bus) { struct device_node *child = NULL; @@ -381,9 +380,10 @@ static void __devinit of_scan_bus(struct device_node *node, do_bus_setup(bus); } +EXPORT_SYMBOL(of_scan_bus); -static void __devinit of_scan_pci_bridge(struct device_node *node, - struct pci_dev *dev) +void __devinit of_scan_pci_bridge(struct device_node *node, + struct pci_dev *dev) { struct pci_bus *bus; u32 *busrange, *ranges; @@ -464,9 +464,10 @@ static void __devinit of_scan_pci_bridge(struct device_node *node, else if (mode == PCI_PROBE_NORMAL) pci_scan_child_bus(bus); } +EXPORT_SYMBOL(of_scan_pci_bridge); #endif /* CONFIG_PPC_MULTIPLATFORM */ -static void __devinit scan_phb(struct pci_controller *hose) +void __devinit scan_phb(struct pci_controller *hose) { struct pci_bus *bus; struct device_node *node = hose->arch_data; diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c index 3ad15c90fbbd..3c3f19192fcc 100644 --- a/arch/ppc64/kernel/rtas_pci.c +++ b/arch/ppc64/kernel/rtas_pci.c @@ -440,7 +440,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) struct device_node *root = of_find_node_by_path("/"); unsigned int root_size_cells = 0; struct pci_controller *phb; - struct pci_bus *bus; int primary; root_size_cells = prom_n_size_cells(root); @@ -456,10 +455,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) of_node_put(root); pci_devs_phb_init_dynamic(phb); - phb->last_busno = 0xff; - bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data); - phb->bus = bus; - phb->last_busno = bus->subordinate; + scan_phb(phb); return phb; } diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index a88728fba8f6..13aacff755f3 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -34,6 +34,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, void pci_devs_phb_init(void); void pci_devs_phb_init_dynamic(struct pci_controller *phb); +void __devinit scan_phb(struct pci_controller *hose); /* PCI address cache management routines */ void pci_addr_cache_insert_device(struct pci_dev *dev); diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h index 342e2d755550..fafdf885a3cc 100644 --- a/include/asm-ppc64/pci.h +++ b/include/asm-ppc64/pci.h @@ -162,6 +162,14 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus); extern struct pci_controller *init_phb_dynamic(struct device_node *dn); +extern struct pci_dev *of_create_pci_dev(struct device_node *node, + struct pci_bus *bus, int devfn); + +extern void of_scan_pci_bridge(struct device_node *node, + struct pci_dev *dev); + +extern void of_scan_bus(struct device_node *node, struct pci_bus *bus); + extern int pci_read_irq_line(struct pci_dev *dev); extern void pcibios_add_platform_entries(struct pci_dev *dev); -- cgit v1.2.3 From 55b6332ec89a5fc65d1287708cfd9f06f7a88b90 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sat, 5 Nov 2005 14:06:24 -0200 Subject: [PATCH] ppc32: handle access to non-present IO ports on 8xx This adds exception table entries for I/O instructions on and changes MachineCheckException() slightly to cover 8xx specifics (on 8xx the MCE can be generated while executing the IO access instruction itself, which is not the case on PowerMac's, as the comment on traps.c details). Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/kernel/misc.S | 145 +++++++++++++++++++++++++++++++++++++++++------- arch/ppc/kernel/traps.c | 8 ++- include/asm-ppc/io.h | 12 ++-- 3 files changed, 138 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 3056ede2424d..ae6af29938a1 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -25,6 +25,11 @@ #include #include +#ifdef CONFIG_8xx +#define ISYNC_8xx isync +#else +#define ISYNC_8xx +#endif .text .align 5 @@ -800,8 +805,18 @@ _GLOBAL(_insb) subi r4,r4,1 blelr- 00: lbz r5,0(r3) - eieio - stbu r5,1(r4) +01: eieio +02: stbu r5,1(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -811,8 +826,18 @@ _GLOBAL(_outsb) subi r4,r4,1 blelr- 00: lbzu r5,1(r4) - stb r5,0(r3) - eieio +01: stb r5,0(r3) +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -822,8 +847,18 @@ _GLOBAL(_insw) subi r4,r4,2 blelr- 00: lhbrx r5,0,r3 - eieio - sthu r5,2(r4) +01: eieio +02: sthu r5,2(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -833,8 +868,18 @@ _GLOBAL(_outsw) subi r4,r4,2 blelr- 00: lhzu r5,2(r4) - eieio - sthbrx r5,0,r3 +01: eieio +02: sthbrx r5,0,r3 + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -844,8 +889,18 @@ _GLOBAL(_insl) subi r4,r4,4 blelr- 00: lwbrx r5,0,r3 - eieio - stwu r5,4(r4) +01: eieio +02: stwu r5,4(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -855,8 +910,18 @@ _GLOBAL(_outsl) subi r4,r4,4 blelr- 00: lwzu r5,4(r4) - stwbrx r5,0,r3 - eieio +01: stwbrx r5,0,r3 +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -867,8 +932,18 @@ _GLOBAL(_insw_ns) subi r4,r4,2 blelr- 00: lhz r5,0(r3) - eieio - sthu r5,2(r4) +01: eieio +02: sthu r5,2(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -879,8 +954,18 @@ _GLOBAL(_outsw_ns) subi r4,r4,2 blelr- 00: lhzu r5,2(r4) - sth r5,0(r3) - eieio +01: sth r5,0(r3) +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -891,8 +976,18 @@ _GLOBAL(_insl_ns) subi r4,r4,4 blelr- 00: lwz r5,0(r3) - eieio - stwu r5,4(r4) +01: eieio +02: stwu r5,4(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -903,8 +998,18 @@ _GLOBAL(_outsl_ns) subi r4,r4,4 blelr- 00: lwzu r5,4(r4) - stw r5,0(r3) - eieio +01: stw r5,0(r3) +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 16adde6b429d..42d980e82bdc 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -159,7 +159,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) */ static inline int check_io_access(struct pt_regs *regs) { -#ifdef CONFIG_PPC_PMAC +#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx unsigned long msr = regs->msr; const struct exception_table_entry *entry; unsigned int *nip = (unsigned int *)regs->nip; @@ -178,7 +178,11 @@ static inline int check_io_access(struct pt_regs *regs) nip -= 2; else if (*nip == 0x4c00012c) /* isync */ --nip; - if (*nip == 0x7c0004ac || (*nip >> 26) == 3) { + /* eieio from I/O string functions */ + else if ((*nip) == 0x7c0006ac || *(nip+1) == 0x7c0006ac) + nip += 2; + if (*nip == 0x7c0004ac || (*nip >> 26) == 3 || + (*(nip+1) >> 26) == 3) { /* sync or twi */ unsigned int rb; diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index f7f614dfc648..2bfdf9c98459 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -237,9 +237,9 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr) #define outsl(port, buf, nl) _outsl_ns((port)+___IO_BASE, (buf), (nl)) /* - * On powermacs, we will get a machine check exception if we - * try to read data from a non-existent I/O port. Because the - * machine check is an asynchronous exception, it isn't + * On powermacs and 8xx we will get a machine check exception + * if we try to read data from a non-existent I/O port. Because + * the machine check is an asynchronous exception, it isn't * well-defined which instruction SRR0 will point to when the * exception occurs. * With the sequence below (twi; isync; nop), we have found that @@ -258,7 +258,7 @@ extern __inline__ unsigned int name(unsigned int port) \ { \ unsigned int x; \ __asm__ __volatile__( \ - op " %0,0,%1\n" \ + "0:" op " %0,0,%1\n" \ "1: twi 0,%0,0\n" \ "2: isync\n" \ "3: nop\n" \ @@ -269,6 +269,7 @@ extern __inline__ unsigned int name(unsigned int port) \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 2\n" \ + " .long 0b,5b\n" \ " .long 1b,5b\n" \ " .long 2b,5b\n" \ " .long 3b,5b\n" \ @@ -282,11 +283,12 @@ extern __inline__ unsigned int name(unsigned int port) \ extern __inline__ void name(unsigned int val, unsigned int port) \ { \ __asm__ __volatile__( \ - op " %0,0,%1\n" \ + "0:" op " %0,0,%1\n" \ "1: sync\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ " .align 2\n" \ + " .long 0b,2b\n" \ " .long 1b,2b\n" \ ".previous" \ : : "r" (val), "r" (port + ___IO_BASE)); \ -- cgit v1.2.3 From dcad47fc423ac9f4934579af814fa2dad5c8081b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Nov 2005 09:49:43 +1100 Subject: [PATCH] powerpc: Kill ppcdebug The ancient ppcdebug/PPCDBG mechanism is now only used in two places. First, in the hash setup code, one of the bits allows the size of the hash table to be reduced by a factor of 8 - which would be better accomplished with a command line option for that purpose. The other was a bunch of bus walking related messages in the iSeries code, which would seem to be insufficient reason to keep the mechanism. This patch removes the last traces of this mechanism. Built and booted on iSeries and pSeries POWER5 LPAR (ARCH=powerpc). Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup_64.c | 9 +-- arch/powerpc/kernel/signal_32.c | 1 - arch/powerpc/kernel/signal_64.c | 1 - arch/powerpc/mm/hash_utils_64.c | 7 --- arch/powerpc/mm/init_64.c | 1 - arch/powerpc/mm/pgtable_64.c | 1 - arch/powerpc/platforms/iseries/irq.c | 5 -- arch/powerpc/platforms/iseries/pci.c | 37 ----------- arch/powerpc/platforms/iseries/setup.c | 4 -- arch/powerpc/platforms/iseries/smp.c | 1 - arch/powerpc/platforms/pseries/iommu.c | 1 - arch/powerpc/platforms/pseries/lpar.c | 2 +- arch/powerpc/platforms/pseries/ras.c | 2 +- arch/powerpc/sysdev/u3_iommu.c | 1 - arch/ppc64/Kconfig.debug | 4 -- arch/ppc64/kernel/prom.c | 1 - arch/ppc64/kernel/prom_init.c | 1 - arch/ppc64/kernel/udbg.c | 55 ----------------- include/asm-ppc64/ppcdebug.h | 108 --------------------------------- include/asm-ppc64/udbg.h | 3 - 20 files changed, 3 insertions(+), 242 deletions(-) delete mode 100644 include/asm-ppc64/ppcdebug.h (limited to 'include') diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6b52cce872be..5f8154f95f96 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -243,12 +243,6 @@ void __init early_setup(unsigned long dt_ptr) DBG(" -> early_setup()\n"); - /* - * Fill the default DBG level (do we want to keep - * that old mecanism around forever ?) - */ - ppcdbg_initialize(); - /* * Do early initializations using the flattened device * tree, like retreiving the physical memory map or @@ -516,7 +510,6 @@ void __init setup_system(void) printk("-----------------------------------------------------\n"); printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); - printk("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch); printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); printk("systemcfg = 0x%p\n", systemcfg); printk("systemcfg->platform = 0x%x\n", systemcfg->platform); diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 876c57c11365..081d931eae48 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -44,7 +44,6 @@ #include #ifdef CONFIG_PPC64 #include "ppc32.h" -#include #include #include #else diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index ec9d0984b6a0..58194e150711 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 6e9e05cce02c..b6970c96d96f 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -194,12 +193,6 @@ void __init htab_initialize(void) htab_size_bytes = get_hashtable_size(); pteg_count = htab_size_bytes >> 7; - /* For debug, make the HTAB 1/8 as big as it normally would be. */ - ifppcdebug(PPCDBG_HTABSIZE) { - pteg_count >>= 3; - htab_size_bytes = pteg_count << 7; - } - htab_hash_mask = pteg_count - 1; if (systemcfg->platform & PLATFORM_LPAR) { diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index b0fc822ec29f..aa98b79e734c 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index b79a78206135..d1fbd3fe684f 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index c1135912cc05..a06603d84a45 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -227,8 +226,6 @@ static void iSeries_enable_IRQ(unsigned int irq) /* Unmask secondary INTA */ mask = 0x80000000; HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); } /* This is called by iSeries_activate_IRQs */ @@ -310,8 +307,6 @@ static void iSeries_disable_IRQ(unsigned int irq) /* Mask secondary INTA */ mask = 0x80000000; HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); } /* diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 7d7d5884343f..4b75131773a6 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -207,10 +206,6 @@ static struct device_node *build_device_node(HvBusNumber Bus, struct device_node *node; struct pci_dn *pdn; - PPCDBG(PPCDBG_BUSWALK, - "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", - Bus, SubBus, AgentId, Function); - node = kmalloc(sizeof(struct device_node), GFP_KERNEL); if (node == NULL) return NULL; @@ -243,8 +238,6 @@ unsigned long __init find_and_init_phbs(void) struct pci_controller *phb; HvBusNumber bus; - PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); - /* Check all possible buses. */ for (bus = 0; bus < 256; bus++) { int ret = HvCallXm_testBus(bus); @@ -261,9 +254,6 @@ unsigned long __init find_and_init_phbs(void) phb->last_busno = bus; phb->ops = &iSeries_pci_ops; - PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", - phb, bus); - /* Find and connect the devices. */ scan_PHB_slots(phb); } @@ -285,11 +275,9 @@ unsigned long __init find_and_init_phbs(void) */ void iSeries_pcibios_init(void) { - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); iomm_table_initialize(); find_and_init_phbs(); io_page_mask = -1; - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); } /* @@ -301,8 +289,6 @@ void __init iSeries_pci_final_fixup(void) struct device_node *node; int DeviceCount = 0; - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); - /* Fix up at the device node and pci_dev relationship */ mf_display_src(0xC9000100); @@ -316,9 +302,6 @@ void __init iSeries_pci_final_fixup(void) ++DeviceCount; pdev->sysdata = (void *)node; PCI_DN(node)->pcidev = pdev; - PPCDBG(PPCDBG_BUSWALK, - "pdev 0x%p <==> DevNode 0x%p\n", - pdev, node); allocate_device_bars(pdev); iSeries_Device_Information(pdev, DeviceCount); iommu_devnode_init_iSeries(node); @@ -333,13 +316,10 @@ void __init iSeries_pci_final_fixup(void) void pcibios_fixup_bus(struct pci_bus *PciBus) { - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n", - PciBus->number); } void pcibios_fixup_resources(struct pci_dev *pdev) { - PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev); } /* @@ -401,9 +381,6 @@ static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, printk("found device at bus %d idsel %d func %d (AgentId %x)\n", bus, IdSel, Function, AgentId); /* Connect EADs: 0x18.00.12 = 0x00 */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:Connect EADs: 0x%02X.%02X.%02X\n", - bus, SubBus, AgentId); HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, iseries_hv_addr(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo)); @@ -414,14 +391,6 @@ static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, BridgeInfo->maxAgents, BridgeInfo->maxSubBusNumber, BridgeInfo->logicalSlotNumber); - PPCDBG(PPCDBG_BUSWALK, - "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) { /* Scan_Bridge_Slot...: 0x18.00.12 */ @@ -454,9 +423,6 @@ static int scan_bridge_slot(HvBusNumber Bus, /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - PPCDBG(PPCDBG_BUSWALK, - "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", - Bus, 0, EADsIdSel, Irq); /* * Connect all functions of any device found. @@ -482,9 +448,6 @@ static int scan_bridge_slot(HvBusNumber Bus, printk("read vendor ID: %x\n", VendorId); /* FoundDevice: 0x18.28.10 = 0x12AE */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n", - Bus, SubBus, AgentId, VendorId, Irq); HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq); if (HvRc != 0) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fda712b42168..36f89e9ec7d0 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -71,8 +71,6 @@ extern void hvlog(char *fmt, ...); #endif /* Function Prototypes */ -extern void ppcdbg_initialize(void); - static void build_iSeries_Memory_Map(void); static void iseries_shared_idle(void); static void iseries_dedicated_idle(void); @@ -309,8 +307,6 @@ static void __init iSeries_init_early(void) ppc64_firmware_features = FW_FEATURE_ISERIES; - ppcdbg_initialize(); - ppc64_interrupt_controller = IC_ISERIES; #if defined(CONFIG_BLK_DEV_INITRD) diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index 3336bad67724..fcb094ec6aec 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 513e27231493..8a99902c7ef7 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index e384a5a91796..d84d76f0026b 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -31,13 +31,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 6562ff4b0a82..fbd214d68b07 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; static DEFINE_SPINLOCK(ras_log_buf_lock); diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c index 607722178c1a..543d65909812 100644 --- a/arch/powerpc/sysdev/u3_iommu.c +++ b/arch/powerpc/sysdev/u3_iommu.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug index f16a5030527b..b258c9314a1b 100644 --- a/arch/ppc64/Kconfig.debug +++ b/arch/ppc64/Kconfig.debug @@ -55,10 +55,6 @@ config XMON_DEFAULT xmon is normally disabled unless booted with 'xmon=on'. Use 'xmon=off' to disable xmon init during runtime. -config PPCDBG - bool "Include PPCDBG realtime debugging" - depends on DEBUG_KERNEL - config IRQSTACKS bool "Use separate kernel stacks when processing interrupts" help diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 97bfceb5353b..a4cb97a25819 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index a4bbca6dbb8b..e72b3f9061f0 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c index d49c3613c8ec..0d878e72fc44 100644 --- a/arch/ppc64/kernel/udbg.c +++ b/arch/ppc64/kernel/udbg.c @@ -10,12 +10,10 @@ */ #include -#define WANT_PPCDBG_TAB /* Only defined here */ #include #include #include #include -#include #include void (*udbg_putc)(unsigned char c); @@ -89,59 +87,6 @@ void udbg_printf(const char *fmt, ...) va_end(args); } -/* PPCDBG stuff */ - -u64 ppc64_debug_switch; - -/* Special print used by PPCDBG() macro */ -void udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...) -{ - unsigned long active_debugs = debug_flags & ppc64_debug_switch; - - if (active_debugs) { - va_list ap; - unsigned char buf[UDBG_BUFSIZE]; - unsigned long i, len = 0; - - for (i=0; i < PPCDBG_NUM_FLAGS; i++) { - if (((1U << i) & active_debugs) && - trace_names[i]) { - len += strlen(trace_names[i]); - udbg_puts(trace_names[i]); - break; - } - } - - snprintf(buf, UDBG_BUFSIZE, " [%s]: ", current->comm); - len += strlen(buf); - udbg_puts(buf); - - while (len < 18) { - udbg_puts(" "); - len++; - } - - va_start(ap, fmt); - vsnprintf(buf, UDBG_BUFSIZE, fmt, ap); - udbg_puts(buf); - va_end(ap); - } -} - -unsigned long udbg_ifdebug(unsigned long flags) -{ - return (flags & ppc64_debug_switch); -} - -/* - * Initialize the PPCDBG state. Called before relocation has been enabled. - */ -void __init ppcdbg_initialize(void) -{ - ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */ - /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */; -} - /* * Early boot console based on udbg */ diff --git a/include/asm-ppc64/ppcdebug.h b/include/asm-ppc64/ppcdebug.h deleted file mode 100644 index fd7f696065c4..000000000000 --- a/include/asm-ppc64/ppcdebug.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef __PPCDEBUG_H -#define __PPCDEBUG_H -/******************************************************************** - * Author: Adam Litke, IBM Corp - * (c) 2001 - * - * This file contains definitions and macros for a runtime debugging - * system for ppc64 (This should also work on 32 bit with a few - * adjustments. - * - * 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 - -#define PPCDBG_BITVAL(X) ((1UL)<<((unsigned long)(X))) - -/* Defined below are the bit positions of various debug flags in the - * ppc64_debug_switch variable. - * -- When adding new values, please enter them into trace names below -- - * - * Values 62 & 63 can be used to stress the hardware page table management - * code. They must be set statically, any attempt to change them dynamically - * would be a very bad idea. - */ -#define PPCDBG_MMINIT PPCDBG_BITVAL(0) -#define PPCDBG_MM PPCDBG_BITVAL(1) -#define PPCDBG_SYS32 PPCDBG_BITVAL(2) -#define PPCDBG_SYS32NI PPCDBG_BITVAL(3) -#define PPCDBG_SYS32X PPCDBG_BITVAL(4) -#define PPCDBG_SYS32M PPCDBG_BITVAL(5) -#define PPCDBG_SYS64 PPCDBG_BITVAL(6) -#define PPCDBG_SYS64NI PPCDBG_BITVAL(7) -#define PPCDBG_SYS64X PPCDBG_BITVAL(8) -#define PPCDBG_SIGNAL PPCDBG_BITVAL(9) -#define PPCDBG_SIGNALXMON PPCDBG_BITVAL(10) -#define PPCDBG_BINFMT32 PPCDBG_BITVAL(11) -#define PPCDBG_BINFMT64 PPCDBG_BITVAL(12) -#define PPCDBG_BINFMTXMON PPCDBG_BITVAL(13) -#define PPCDBG_BINFMT_32ADDR PPCDBG_BITVAL(14) -#define PPCDBG_ALIGNFIXUP PPCDBG_BITVAL(15) -#define PPCDBG_TCEINIT PPCDBG_BITVAL(16) -#define PPCDBG_TCE PPCDBG_BITVAL(17) -#define PPCDBG_PHBINIT PPCDBG_BITVAL(18) -#define PPCDBG_SMP PPCDBG_BITVAL(19) -#define PPCDBG_BOOT PPCDBG_BITVAL(20) -#define PPCDBG_BUSWALK PPCDBG_BITVAL(21) -#define PPCDBG_PROM PPCDBG_BITVAL(22) -#define PPCDBG_RTAS PPCDBG_BITVAL(23) -#define PPCDBG_HTABSTRESS PPCDBG_BITVAL(62) -#define PPCDBG_HTABSIZE PPCDBG_BITVAL(63) -#define PPCDBG_NONE (0UL) -#define PPCDBG_ALL (0xffffffffUL) - -/* The default initial value for the debug switch */ -#define PPC_DEBUG_DEFAULT 0 -/* #define PPC_DEBUG_DEFAULT PPCDBG_ALL */ - -#define PPCDBG_NUM_FLAGS 64 - -extern u64 ppc64_debug_switch; - -#ifdef WANT_PPCDBG_TAB -/* A table of debug switch names to allow name lookup in xmon - * (and whoever else wants it. - */ -char *trace_names[PPCDBG_NUM_FLAGS] = { - /* Known debug names */ - "mminit", "mm", - "syscall32", "syscall32_ni", "syscall32x", "syscall32m", - "syscall64", "syscall64_ni", "syscall64x", - "signal", "signal_xmon", - "binfmt32", "binfmt64", "binfmt_xmon", "binfmt_32addr", - "alignfixup", "tceinit", "tce", "phb_init", - "smp", "boot", "buswalk", "prom", - "rtas" -}; -#else -extern char *trace_names[64]; -#endif /* WANT_PPCDBG_TAB */ - -#ifdef CONFIG_PPCDBG -/* Macro to conditionally print debug based on debug_switch */ -#define PPCDBG(...) udbg_ppcdbg(__VA_ARGS__) - -/* Macro to conditionally call a debug routine based on debug_switch */ -#define PPCDBGCALL(FLAGS,FUNCTION) ifppcdebug(FLAGS) FUNCTION - -/* Macros to test for debug states */ -#define ifppcdebug(FLAGS) if (udbg_ifdebug(FLAGS)) -#define ppcdebugset(FLAGS) (udbg_ifdebug(FLAGS)) -#define PPCDBG_BINFMT (test_thread_flag(TIF_32BIT) ? PPCDBG_BINFMT32 : PPCDBG_BINFMT64) - -#else -#define PPCDBG(...) do {;} while (0) -#define PPCDBGCALL(FLAGS,FUNCTION) do {;} while (0) -#define ifppcdebug(...) if (0) -#define ppcdebugset(FLAGS) (0) -#endif /* CONFIG_PPCDBG */ - -#endif /*__PPCDEBUG_H */ diff --git a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h index 8192fb8541cc..e3b927991851 100644 --- a/include/asm-ppc64/udbg.h +++ b/include/asm-ppc64/udbg.h @@ -23,9 +23,6 @@ extern int udbg_read(char *buf, int buflen); extern void register_early_udbg_console(void); extern void udbg_printf(const char *fmt, ...); -extern void udbg_ppcdbg(unsigned long flags, const char *fmt, ...); -extern unsigned long udbg_ifdebug(unsigned long flags); -extern void __init ppcdbg_initialize(void); extern void udbg_init_uart(void __iomem *comport, unsigned int speed); -- cgit v1.2.3 From 2249ca9d60d3a8a1f6f223f0f0a0283fcb7ce33e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 7 Nov 2005 13:18:13 +1100 Subject: powerpc: Various UP build fixes Mostly this involves adding #include , since that defines things like boot_cpuid[_phys] and [gs]et_hard_smp_processor_id, which are SMP-related but still needed on UP. This incorporates fixes posted by Olof Johansson and Heikki Lindholm. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 2 -- arch/powerpc/kernel/time.c | 5 +---- arch/powerpc/lib/locks.c | 1 + arch/powerpc/mm/numa.c | 1 + arch/powerpc/platforms/pseries/iommu.c | 1 + arch/powerpc/platforms/pseries/lpar.c | 1 + arch/powerpc/platforms/pseries/setup.c | 1 + arch/ppc64/kernel/idle.c | 1 + arch/ppc64/kernel/machine_kexec.c | 1 + arch/ppc64/kernel/sysfs.c | 1 + include/asm-powerpc/smp.h | 4 +++- 11 files changed, 12 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index b7fc2d884950..751f5ddea913 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -608,7 +608,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) return 0; } -#ifdef CONFIG_SMP /* This version can't take the spinlock, because it never returns */ struct rtas_args rtas_stop_self_args = { @@ -633,7 +632,6 @@ void rtas_stop_self(void) panic("Alas, I survived.\n"); } -#endif /* * Call early during boot, before mem init or bootmem, to retreive the RTAS diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 6996a593dcb3..1c7ea5e06311 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -61,6 +61,7 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #include @@ -118,10 +119,6 @@ static unsigned adjusting_time = 0; unsigned long ppc_proc_freq; unsigned long ppc_tb_freq; -#ifdef CONFIG_PPC32 /* XXX for now */ -#define boot_cpuid 0 -#endif - u64 tb_last_jiffy __cacheline_aligned_in_smp; unsigned long tb_last_stamp; diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 2a912f411eb4..35bd03c41dd1 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -23,6 +23,7 @@ #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) #include #include +#include void __spin_yield(raw_spinlock_t *lock) { diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 4035cad8d7f1..da09ba03c424 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -21,6 +21,7 @@ #include #include #include +#include static int numa_enabled = 1; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 8a99902c7ef7..fcc50bfd43fd 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index d84d76f0026b..8a42006370c5 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 65bee939eecc..934d7006353f 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -65,6 +65,7 @@ #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 8abd2ad92832..8fec27469802 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c @@ -28,6 +28,7 @@ #include #include #include +#include extern void power4_idle(void); diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index ff8679f260f3..07ea03598c00 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -24,6 +24,7 @@ #include #include /* _end */ #include +#include #define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */ diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 6654b350979c..e99ec62c2c52 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c @@ -20,6 +20,7 @@ #include #include #include +#include static DEFINE_PER_CPU(struct cpu, cpu_devices); diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h index 8bcdd0faefea..98581e5a8279 100644 --- a/include/asm-powerpc/smp.h +++ b/include/asm-powerpc/smp.h @@ -86,7 +86,6 @@ extern void __cpu_die(unsigned int cpu); #else /* for UP */ #define smp_setup_cpu_maps() -#define smp_release_cpus() #endif /* CONFIG_SMP */ @@ -94,6 +93,9 @@ extern void __cpu_die(unsigned int cpu); #define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id) #define set_hard_smp_processor_id(CPU, VAL) \ do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0) + +extern void smp_release_cpus(void); + #else /* 32-bit */ #ifndef CONFIG_SMP -- cgit v1.2.3 From 76032de898f34db55b5048349db56557828a1390 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 7 Nov 2005 13:12:03 +1100 Subject: [PATCH] powerpc: Make ppc_md.set_dabr non 64-bit specific Define ppc_md.set_dabr for both 32 + 64 bit. Cleanup the implementation for pSeries also, it was needlessly complex. Now we just do two firmware tests at setup time, and use one of two functions, rather than using one function and testing on every call. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 4 +--- arch/powerpc/platforms/pseries/plpar_wrappers.h | 10 ---------- arch/powerpc/platforms/pseries/setup.c | 17 ++++++++++------- include/asm-powerpc/machdep.h | 4 +++- 4 files changed, 14 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 96843211cc5c..29f6e875cf1c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -46,10 +46,10 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #include -#include #endif extern unsigned long _get_SP(void); @@ -203,10 +203,8 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) int set_dabr(unsigned long dabr) { -#ifdef CONFIG_PPC64 if (ppc_md.set_dabr) return ppc_md.set_dabr(dabr); -#endif mtspr(SPRN_DABR, dabr); return 0; diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 382f8c5b0e7c..3bd1b3e06003 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -107,14 +107,4 @@ static inline long plpar_put_term_char(unsigned long termno, unsigned long len, lbuf[1]); } -static inline long plpar_set_xdabr(unsigned long address, unsigned long flags) -{ - return plpar_hcall_norets(H_SET_XDABR, address, flags); -} - -static inline long plpar_set_dabr(unsigned long val) -{ - return plpar_hcall_norets(H_SET_DABR, val); -} - #endif /* _PSERIES_PLPAR_WRAPPERS_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 934d7006353f..e78c39368841 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -354,14 +354,15 @@ static void pSeries_mach_cpu_die(void) static int pseries_set_dabr(unsigned long dabr) { - if (firmware_has_feature(FW_FEATURE_XDABR)) { - /* We want to catch accesses from kernel and userspace */ - return plpar_set_xdabr(dabr, H_DABRX_KERNEL | H_DABRX_USER); - } - - return plpar_set_dabr(dabr); + return plpar_hcall_norets(H_SET_DABR, dabr); } +static int pseries_set_xdabr(unsigned long dabr) +{ + /* We want to catch accesses from kernel and userspace */ + return plpar_hcall_norets(H_SET_XDABR, dabr, + H_DABRX_KERNEL | H_DABRX_USER); +} /* * Early initialization. Relocation is on but do not reference unbolted pages @@ -397,8 +398,10 @@ static void __init pSeries_init_early(void) DBG("Hello World !\n"); } - if (firmware_has_feature(FW_FEATURE_XDABR | FW_FEATURE_DABR)) + if (firmware_has_feature(FW_FEATURE_DABR)) ppc_md.set_dabr = pseries_set_dabr; + else if (firmware_has_feature(FW_FEATURE_XDABR)) + ppc_md.set_dabr = pseries_set_xdabr; iommu_init_early_pSeries(); diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 629ca964b974..b623bc4a1553 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -80,7 +80,6 @@ struct machdep_calls { void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); void (*irq_bus_setup)(struct pci_bus *bus); - int (*set_dabr)(unsigned long dabr); #endif int (*probe)(int platform); @@ -156,6 +155,9 @@ struct machdep_calls { platform, called once per cpu. */ void (*enable_pmcs)(void); + /* Set DABR for this platform, leave empty for default implemenation */ + int (*set_dabr)(unsigned long dabr); + #ifdef CONFIG_PPC32 /* XXX for now */ /* A general init function, called by ppc_init in init/main.c. May be NULL. */ -- cgit v1.2.3 From 193515d51ccb363165d6b09e9ba5c21089e34bad Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 7 Nov 2005 00:59:37 -0500 Subject: [libata] eliminate use of drivers/scsi/scsi.h compatibility header/defines --- drivers/scsi/ahci.c | 4 ++-- drivers/scsi/ata_piix.c | 3 +-- drivers/scsi/libata-core.c | 2 +- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/pdc_adma.c | 3 +-- drivers/scsi/sata_mv.c | 4 ++-- drivers/scsi/sata_nv.c | 3 +-- drivers/scsi/sata_promise.c | 4 ++-- drivers/scsi/sata_qstor.c | 3 +-- drivers/scsi/sata_sil.c | 3 +-- drivers/scsi/sata_sil24.c | 4 ++-- drivers/scsi/sata_sis.c | 3 +-- drivers/scsi/sata_svw.c | 3 +-- drivers/scsi/sata_sx4.c | 4 ++-- drivers/scsi/sata_uli.c | 3 +-- drivers/scsi/sata_via.c | 3 +-- drivers/scsi/sata_vsc.c | 3 +-- include/linux/libata.h | 6 +++--- 18 files changed, 25 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 4612312c0c2d..10c470e7d316 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -42,8 +42,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include @@ -196,7 +196,7 @@ static u8 ahci_check_status(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); -static Scsi_Host_Template ahci_sht = { +static struct scsi_host_template ahci_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 7f8aa1b552ce..a1bd8d95623c 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -46,7 +46,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -128,7 +127,7 @@ static struct pci_driver piix_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template piix_sht = { +static struct scsi_host_template piix_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1c1a7caf785e..98769a3d31ae 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -51,8 +51,8 @@ #include #include #include -#include "scsi.h" #include "scsi_priv.h" +#include #include #include #include diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index eb604b0a8990..38a895ebe826 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -37,9 +37,9 @@ #include #include #include -#include "scsi.h" #include #include +#include #include #include #include diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index a50588c60fab..78b4ff117af6 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -41,7 +41,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -139,7 +138,7 @@ static u8 adma_bmdma_status(struct ata_port *ap); static void adma_irq_clear(struct ata_port *ap); static void adma_eng_timeout(struct ata_port *ap); -static Scsi_Host_Template adma_ata_sht = { +static struct scsi_host_template adma_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 0f469e3dabe2..93d55233af7b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -30,8 +30,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include @@ -270,7 +270,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, static void mv_eng_timeout(struct ata_port *ap); static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static Scsi_Host_Template mv_sht = { +static struct scsi_host_template mv_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index d573888eda76..37a4fae95ed4 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -62,7 +62,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -219,7 +218,7 @@ static struct pci_driver nv_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template nv_sht = { +static struct scsi_host_template nv_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index b41c977d6fab..9edc9d91efc3 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -39,8 +39,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include #include "sata_promise.h" @@ -94,7 +94,7 @@ static void pdc_irq_clear(struct ata_port *ap); static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_ata_sht = { +static struct scsi_host_template pdc_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 65502c157a54..d274ab235781 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -36,7 +36,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -128,7 +127,7 @@ static u8 qs_bmdma_status(struct ata_port *ap); static void qs_irq_clear(struct ata_port *ap); static void qs_eng_timeout(struct ata_port *ap); -static Scsi_Host_Template qs_ata_sht = { +static struct scsi_host_template qs_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 435f7e0085ec..d0e3c3c6c25f 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -42,7 +42,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -131,7 +130,7 @@ static struct pci_driver sil_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template sil_sht = { +static struct scsi_host_template sil_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index e6c8e89c226f..4682a50650b4 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -37,7 +37,7 @@ #include #include #include -#include "scsi.h" +#include #include #include @@ -255,7 +255,7 @@ static struct pci_driver sil24_pci_driver = { .remove = ata_pci_remove_one, /* safe? */ }; -static Scsi_Host_Template sil24_sht = { +static struct scsi_host_template sil24_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 42288be0e561..42d7c4e92501 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -39,7 +39,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -83,7 +82,7 @@ static struct pci_driver sis_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template sis_sht = { +static struct scsi_host_template sis_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index db615ff794d8..9895d1caefcf 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -45,7 +45,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -284,7 +283,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, #endif /* CONFIG_PPC_OF */ -static Scsi_Host_Template k2_sata_sht = { +static struct scsi_host_template k2_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index f859bbd681ed..d5a38784352b 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -39,8 +39,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include #include "sata_promise.h" @@ -177,7 +177,7 @@ static void pdc20621_irq_clear(struct ata_port *ap); static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_sata_sht = { +static struct scsi_host_template pdc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index a5e245c098e1..cf0baaa4e045 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -33,7 +33,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -71,7 +70,7 @@ static struct pci_driver uli_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template uli_sht = { +static struct scsi_host_template uli_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index b3ecdbe400e9..ab19d2ba2a4b 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -42,7 +42,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -90,7 +89,7 @@ static struct pci_driver svia_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template svia_sht = { +static struct scsi_host_template svia_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index bb84ba0c7e83..ce8a2fd7da84 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -43,7 +43,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -219,7 +218,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, } -static Scsi_Host_Template vsc_sata_sht = { +static struct scsi_host_template vsc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/include/linux/libata.h b/include/linux/libata.h index dcd17e7458ab..6f0752219f64 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -214,7 +214,7 @@ struct ata_probe_ent { struct list_head node; struct device *dev; const struct ata_port_operations *port_ops; - Scsi_Host_Template *sht; + struct scsi_host_template *sht; struct ata_ioports port[ATA_MAX_PORTS]; unsigned int n_ports; unsigned int hard_port_no; @@ -398,7 +398,7 @@ struct ata_port_operations { }; struct ata_port_info { - Scsi_Host_Template *sht; + struct scsi_host_template *sht; unsigned long host_flags; unsigned long pio_mask; unsigned long mwdma_mask; @@ -433,7 +433,7 @@ extern void ata_pci_remove_one (struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); extern void ata_host_set_remove(struct ata_host_set *host_set); -extern int ata_scsi_detect(Scsi_Host_Template *sht); +extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); -- cgit v1.2.3 From 182ec4eee397543101a6db8906ed88727d3f7e53 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:16:07 +0000 Subject: [JFFS2] Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- fs/Kconfig | 10 +-- fs/jffs2/background.c | 4 +- fs/jffs2/build.c | 28 ++++---- fs/jffs2/compr.c | 28 ++++---- fs/jffs2/compr.h | 4 +- fs/jffs2/compr_rtime.c | 32 ++++----- fs/jffs2/compr_rubin.c | 37 +++++----- fs/jffs2/compr_rubin.h | 6 +- fs/jffs2/compr_zlib.c | 14 ++-- fs/jffs2/comprtest.c | 30 ++++---- fs/jffs2/debug.c | 30 ++++---- fs/jffs2/debug.h | 10 +-- fs/jffs2/dir.c | 74 +++++++++---------- fs/jffs2/erase.c | 28 ++++---- fs/jffs2/file.c | 20 +++--- fs/jffs2/fs.c | 56 +++++++-------- fs/jffs2/gc.c | 112 ++++++++++++++--------------- fs/jffs2/histo.h | 2 +- fs/jffs2/histo_mips.h | 2 +- fs/jffs2/ioctl.c | 6 +- fs/jffs2/malloc.c | 4 +- fs/jffs2/nodelist.c | 170 ++++++++++++++++++++++---------------------- fs/jffs2/nodelist.h | 26 +++---- fs/jffs2/nodemgmt.c | 58 +++++++-------- fs/jffs2/os-linux.h | 8 +-- fs/jffs2/read.c | 16 ++--- fs/jffs2/readinode.c | 84 +++++++++++----------- fs/jffs2/scan.c | 52 +++++++------- fs/jffs2/summary.c | 8 +-- fs/jffs2/super.c | 16 ++--- fs/jffs2/symlink.c | 8 +-- fs/jffs2/wbuf.c | 128 ++++++++++++++++----------------- fs/jffs2/write.c | 68 +++++++++--------- include/linux/jffs2.h | 12 ++-- include/linux/jffs2_fs_i.h | 4 +- include/linux/jffs2_fs_sb.h | 14 ++-- 36 files changed, 604 insertions(+), 605 deletions(-) (limited to 'include') diff --git a/fs/Kconfig b/fs/Kconfig index 37d86c5072eb..660a0c04d6b9 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1084,10 +1084,10 @@ config JFFS2_ZLIB default y help Zlib is designed to be a free, general-purpose, legally unencumbered, - lossless data-compression library for use on virtually any computer + lossless data-compression library for use on virtually any computer hardware and operating system. See for further information. - + Say 'Y' if unsure. config JFFS2_RTIME @@ -1109,7 +1109,7 @@ choice default JFFS2_CMODE_PRIORITY depends on JFFS2_FS help - You can set here the default compression mode of JFFS2 from + You can set here the default compression mode of JFFS2 from the available compression modes. Don't touch if unsure. config JFFS2_CMODE_NONE @@ -1120,13 +1120,13 @@ config JFFS2_CMODE_NONE config JFFS2_CMODE_PRIORITY bool "priority" help - Tries the compressors in a predefinied order and chooses the first + Tries the compressors in a predefinied order and chooses the first successful one. config JFFS2_CMODE_SIZE bool "size (EXPERIMENTAL)" help - Tries all compressors and chooses the one which has the smallest + Tries all compressors and chooses the one which has the smallest result. endchoice diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 8210ac16a368..7b77a9541125 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -51,7 +51,7 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", pid)); wait_for_completion(&c->gc_thread_start); } - + return ret; } @@ -101,7 +101,7 @@ static int jffs2_garbage_collect_thread(void *_c) cond_resched(); - /* Put_super will send a SIGKILL and then wait on the sem. + /* Put_super will send a SIGKILL and then wait on the sem. */ while (signal_pending(current)) { siginfo_t info; diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index af6d2ec01366..fff108bb118b 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.84 2005/09/27 13:40:49 dedekind Exp $ + * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -129,10 +129,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) for_each_inode(i, c, ic) { if (ic->nlink) continue; - + jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); cond_resched(); - } + } dbg_fsbuild("pass 2a starting\n"); @@ -149,7 +149,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) dbg_fsbuild("pass 2a complete\n"); dbg_fsbuild("freeing temporary data structures\n"); - + /* Finally, we can scan again and free the dirent structs */ for_each_inode(i, c, ic) { while(ic->scan_dents) { @@ -161,7 +161,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) cond_resched(); } c->flags &= ~JFFS2_SB_FLAG_BUILDING; - + dbg_fsbuild("FS build complete\n"); /* Rotate the lists by some number to ensure wear levelling */ @@ -191,7 +191,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_full_dirent *fd; dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino); - + raw = ic->nodes; while (raw != (void *)ic) { struct jffs2_raw_node_ref *next = raw->next_in_ino; @@ -220,7 +220,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, whinged = 1; dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino); - + child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n", @@ -229,11 +229,11 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, continue; } - /* Reduce nlink of the child. If it's now zero, stick it on the + /* Reduce nlink of the child. If it's now zero, stick it on the dead_fds list to be cleaned up later. Else just free the fd */ child_ic->nlink--; - + if (!child_ic->nlink) { dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", fd->ino, fd->name); @@ -248,7 +248,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, } /* - We don't delete the inocache from the hash list and free it yet. + We don't delete the inocache from the hash list and free it yet. The erase code will do that, when all the nodes are completely gone. */ } @@ -262,7 +262,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) because there's not enough free space... */ c->resv_blocks_deletion = 2; - /* Be conservative about how much space we need before we allow writes. + /* Be conservative about how much space we need before we allow writes. On top of that which is required for deletia, require an extra 2% of the medium to be available, for overhead caused by nodes being split across blocks, etc. */ @@ -277,7 +277,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) c->resv_blocks_gctrigger = c->resv_blocks_write + 1; - /* When do we allow garbage collection to merge nodes to make + /* When do we allow garbage collection to merge nodes to make long-term progress at the expense of short-term space exhaustion? */ c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1; @@ -303,7 +303,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", c->nospc_dirty_size); -} +} int jffs2_do_mount_fs(struct jffs2_sb_info *c) { @@ -355,7 +355,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) vfree(c->blocks); - else + else #endif kfree(c->blocks); diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index c9e54b97dba8..e7944e665b9f 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ + * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -36,16 +36,16 @@ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_co * data. * * Returns: Lower byte to be stored with data indicating compression type used. - * Zero is used to show that the data could not be compressed - the + * Zero is used to show that the data could not be compressed - the * compressed version was actually larger than the original. * Upper byte will be used later. (soon) * * If the cdata buffer isn't large enough to hold all the uncompressed data, - * jffs2_compress should compress as much as will fit, and should set + * jffs2_compress should compress as much as will fit, and should set * *datalen accordingly to show the amount of data which were compressed. */ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *data_in, unsigned char **cpage_out, + unsigned char *data_in, unsigned char **cpage_out, uint32_t *datalen, uint32_t *cdatalen) { int ret = JFFS2_COMPR_NONE; @@ -164,7 +164,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint16_t comprtype, unsigned char *cdata_in, + uint16_t comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) { struct jffs2_compressor *this; @@ -298,7 +298,7 @@ char *jffs2_stats(void) act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); act_buf += sprintf(act_buf,"%10s ","none"); - act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, + act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, none_stat_compr_size, none_stat_decompr_blocks); spin_lock(&jffs2_compressor_list_lock); list_for_each_entry(this, &jffs2_compressor_list, list) { @@ -307,8 +307,8 @@ char *jffs2_stats(void) act_buf += sprintf(act_buf,"- "); else act_buf += sprintf(act_buf,"+ "); - act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, - this->stat_compr_new_size, this->stat_compr_orig_size, + act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, + this->stat_compr_new_size, this->stat_compr_orig_size, this->stat_decompr_blocks); act_buf += sprintf(act_buf,"\n"); } @@ -317,7 +317,7 @@ char *jffs2_stats(void) return buf; } -char *jffs2_get_compression_mode_name(void) +char *jffs2_get_compression_mode_name(void) { switch (jffs2_compression_mode) { case JFFS2_COMPR_MODE_NONE: @@ -330,7 +330,7 @@ char *jffs2_get_compression_mode_name(void) return "unkown"; } -int jffs2_set_compression_mode_name(const char *name) +int jffs2_set_compression_mode_name(const char *name) { if (!strcmp("none",name)) { jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; @@ -355,7 +355,7 @@ static int jffs2_compressor_Xable(const char *name, int disabled) if (!strcmp(this->name, name)) { this->disabled = disabled; spin_unlock(&jffs2_compressor_list_lock); - return 0; + return 0; } } spin_unlock(&jffs2_compressor_list_lock); @@ -385,7 +385,7 @@ int jffs2_set_compressor_priority(const char *name, int priority) } } spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); + printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); return 1; reinsert: /* list is sorted in the order of priority, so if @@ -412,7 +412,7 @@ void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) kfree(comprbuf); } -int jffs2_compressors_init(void) +int jffs2_compressors_init(void) { /* Registering compressors */ #ifdef CONFIG_JFFS2_ZLIB @@ -440,7 +440,7 @@ int jffs2_compressors_init(void) return 0; } -int jffs2_compressors_exit(void) +int jffs2_compressors_exit(void) { /* Unregistering compressors */ #ifdef CONFIG_JFFS2_RUBIN diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 9ec6e37d3833..a77e830d85c5 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -4,10 +4,10 @@ * Copyright (C) 2004 Ferenc Havasi , * University of Szeged, Hungary * - * For licensing information, see the file 'LICENCE' in the + * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ + * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $ * */ diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 393129418666..2eb1b7428d16 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include #include "compr.h" /* _compress returns the compressed size, -1 if bigger */ @@ -38,19 +38,19 @@ static int jffs2_rtime_compress(unsigned char *data_in, int outpos = 0; int pos=0; - memset(positions,0,sizeof(positions)); - + memset(positions,0,sizeof(positions)); + while (pos < (*sourcelen) && outpos <= (*dstlen)-2) { int backpos, runlen=0; unsigned char value; - + value = data_in[pos]; cpage_out[outpos++] = data_in[pos++]; - + backpos = positions[value]; positions[value]=pos; - + while ((backpos < pos) && (pos < (*sourcelen)) && (data_in[pos]==data_in[backpos++]) && (runlen<255)) { pos++; @@ -63,12 +63,12 @@ static int jffs2_rtime_compress(unsigned char *data_in, /* We failed */ return -1; } - + /* Tell the caller how much we managed to compress, and how much space it took */ *sourcelen = pos; *dstlen = outpos; return 0; -} +} static int jffs2_rtime_decompress(unsigned char *data_in, @@ -79,19 +79,19 @@ static int jffs2_rtime_decompress(unsigned char *data_in, short positions[256]; int outpos = 0; int pos=0; - - memset(positions,0,sizeof(positions)); - + + memset(positions,0,sizeof(positions)); + while (outpos= outpos) { @@ -101,12 +101,12 @@ static int jffs2_rtime_decompress(unsigned char *data_in, } } else { memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat); - outpos+=repeat; + outpos+=repeat; } } } return 0; -} +} static struct jffs2_compressor jffs2_rtime_comp = { .priority = JFFS2_RTIME_PRIORITY, diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 09422388fb96..e792e675d624 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -11,7 +11,6 @@ * */ - #include #include #include @@ -20,7 +19,7 @@ #include "compr.h" static void init_rubin(struct rubin_state *rs, int div, int *bits) -{ +{ int c; rs->q = 0; @@ -40,7 +39,7 @@ static int encode(struct rubin_state *rs, long A, long B, int symbol) while ((rs->q >= UPPER_BIT_RUBIN) || ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) { rs->bit_number++; - + ret = pushbit(&rs->pp, (rs->q & UPPER_BIT_RUBIN) ? 1 : 0, 0); if (ret) return ret; @@ -68,7 +67,7 @@ static int encode(struct rubin_state *rs, long A, long B, int symbol) static void end_rubin(struct rubin_state *rs) -{ +{ int i; @@ -82,7 +81,7 @@ static void end_rubin(struct rubin_state *rs) static void init_decode(struct rubin_state *rs, int div, int *bits) { - init_rubin(rs, div, bits); + init_rubin(rs, div, bits); /* behalve lower */ rs->rec_q = 0; @@ -188,7 +187,7 @@ static int in_byte(struct rubin_state *rs) -static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, +static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) { int outpos = 0; @@ -198,31 +197,31 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, init_pushpull(&rs.pp, cpage_out, *dstlen * 8, 0, 32); init_rubin(&rs, bit_divider, bits); - + while (pos < (*sourcelen) && !out_byte(&rs, data_in[pos])) pos++; - + end_rubin(&rs); if (outpos > pos) { /* We failed */ return -1; } - - /* Tell the caller how much we managed to compress, + + /* Tell the caller how much we managed to compress, * and how much space it took */ - + outpos = (pushedbits(&rs.pp)+7)/8; - + if (outpos >= pos) return -1; /* We didn't actually compress */ *sourcelen = pos; *dstlen = outpos; return 0; -} +} #if 0 /* _compress returns the compressed size, -1 if bigger */ -int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, +int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen, void *model) { return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); @@ -277,7 +276,7 @@ static int jffs2_dynrubin_compress(unsigned char *data_in, } ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen, &mydstlen); - if (ret) + if (ret) return ret; /* Add back the 8 bytes we took for the probabilities */ @@ -293,19 +292,19 @@ static int jffs2_dynrubin_compress(unsigned char *data_in, return 0; } -static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, +static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, unsigned char *page_out, uint32_t srclen, uint32_t destlen) { int outpos = 0; struct rubin_state rs; - + init_pushpull(&rs.pp, cdata_in, srclen, 0, 0); init_decode(&rs, bit_divider, bits); - + while (outpos < destlen) { page_out[outpos++] = in_byte(&rs); } -} +} static int jffs2_rubinmips_decompress(unsigned char *data_in, diff --git a/fs/jffs2/compr_rubin.h b/fs/jffs2/compr_rubin.h index cf51e34f6574..bf1a93451621 100644 --- a/fs/jffs2/compr_rubin.h +++ b/fs/jffs2/compr_rubin.h @@ -1,7 +1,7 @@ /* Rubin encoder/decoder header */ /* work started at : aug 3, 1994 */ /* last modification : aug 15, 1994 */ -/* $Id: compr_rubin.h,v 1.6 2002/01/25 01:49:26 dwmw2 Exp $ */ +/* $Id: compr_rubin.h,v 1.7 2005/11/07 11:14:38 gleixner Exp $ */ #include "pushpull.h" @@ -11,8 +11,8 @@ struct rubin_state { - unsigned long p; - unsigned long q; + unsigned long p; + unsigned long q; unsigned long rec_q; long bit_number; struct pushpull pp; diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 83f7e0788fd0..4db8be8e90cc 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_zlib.c,v 1.31 2005/05/20 19:30:06 gleixner Exp $ + * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -24,11 +24,11 @@ #include "nodelist.h" #include "compr.h" - /* Plan: call deflate() with avail_in == *sourcelen, - avail_out = *dstlen - 12 and flush == Z_FINISH. + /* Plan: call deflate() with avail_in == *sourcelen, + avail_out = *dstlen - 12 and flush == Z_FINISH. If it doesn't manage to finish, call it again with avail_in == 0 and avail_out set to the remaining 12 - bytes for it to clean up. + bytes for it to clean up. Q: Is 12 bytes sufficient? */ #define STREAM_END_SPACE 12 @@ -89,7 +89,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, def_strm.next_in = data_in; def_strm.total_in = 0; - + def_strm.next_out = cpage_out; def_strm.total_out = 0; @@ -99,7 +99,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", def_strm.avail_in, def_strm.avail_out)); ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); - D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", + D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); if (ret != Z_OK) { D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); @@ -150,7 +150,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in, inf_strm.next_in = data_in; inf_strm.avail_in = srclen; inf_strm.total_in = 0; - + inf_strm.next_out = cpage_out; inf_strm.avail_out = destlen; inf_strm.total_out = 0; diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c index cf51f091d0e7..f0fb8be7740c 100644 --- a/fs/jffs2/comprtest.c +++ b/fs/jffs2/comprtest.c @@ -1,4 +1,4 @@ -/* $Id: comprtest.c,v 1.5 2002/01/03 15:20:44 dwmw2 Exp $ */ +/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */ #include #include @@ -265,9 +265,9 @@ static unsigned char testdata[TESTDATA_LEN] = { static unsigned char comprbuf[TESTDATA_LEN]; static unsigned char decomprbuf[TESTDATA_LEN]; -int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, +int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); -unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, +unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *datalen, uint32_t *cdatalen); int init_module(void ) { @@ -276,10 +276,10 @@ int init_module(void ) { int ret; printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - testdata[0],testdata[1],testdata[2],testdata[3], - testdata[4],testdata[5],testdata[6],testdata[7], - testdata[8],testdata[9],testdata[10],testdata[11], - testdata[12],testdata[13],testdata[14],testdata[15]); + testdata[0],testdata[1],testdata[2],testdata[3], + testdata[4],testdata[5],testdata[6],testdata[7], + testdata[8],testdata[9],testdata[10],testdata[11], + testdata[12],testdata[13],testdata[14],testdata[15]); d = TESTDATA_LEN; c = TESTDATA_LEN; comprtype = jffs2_compress(testdata, comprbuf, &d, &c); @@ -287,18 +287,18 @@ int init_module(void ) { printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n", comprtype, c, d); printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], - comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], - comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], - comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); + comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], + comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], + comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], + comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d); printk("jffs2_decompress returned %d\n", ret); printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], - decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], - decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], - decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); + decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], + decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], + decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], + decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); if (memcmp(decomprbuf, testdata, d)) printk("Compression and decompression corrupted data\n"); else diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 0947284f45dd..1fe17de713e8 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.11 2005/09/21 13:28:35 dedekind Exp $ + * $Id: debug.c,v 1.12 2005/11/07 11:14:39 gleixner Exp $ * */ #include @@ -67,7 +67,7 @@ __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) __jffs2_dbg_fragtree_paranoia_check_nolock(f); up(&f->sem); } - + void __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) { @@ -165,7 +165,7 @@ __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); spin_unlock(&c->erase_completion_lock); } - + void __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) @@ -237,7 +237,7 @@ error: __jffs2_dbg_dump_jeb_nolock(jeb); __jffs2_dbg_dump_block_lists_nolock(c); BUG(); - + } #endif /* JFFS2_DBG_PARANOIA_CHECKS */ @@ -321,7 +321,7 @@ void __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) { printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n"); - + printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size); printk(JFFS2_DBG "used_size: %#08x\n", c->used_size); printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size); @@ -577,15 +577,15 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) { int skip; int i; - + printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n", offs, offs + len, len); i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); - + if (skip != 0) printk(JFFS2_DBG "%#08x: ", offs); - + while (skip--) printk(" "); @@ -598,7 +598,7 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) } printk("%02x ", buf[i]); - + i += 1; } @@ -616,7 +616,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) size_t retlen; uint32_t crc; int ret; - + printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs); ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); @@ -630,13 +630,13 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype)); printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen)); printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc)); - + crc = crc32(0, &node.u, sizeof(node.u) - 4); if (crc != je32_to_cpu(node.u.hdr_crc)) { JFFS2_ERROR("wrong common header CRC.\n"); return; } - + if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) { @@ -668,7 +668,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc)); printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc)); - crc = crc32(0, &node.i, sizeof(node.i) - 8); + crc = crc32(0, &node.i, sizeof(node.i) - 8); if (crc != je32_to_cpu(node.i.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); return; @@ -686,11 +686,11 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "type:\t%#02x\n", node.d.type); printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc)); printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc)); - + node.d.name[node.d.nsize] = '\0'; printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name); - crc = crc32(0, &node.d, sizeof(node.d) - 8); + crc = crc32(0, &node.d, sizeof(node.d) - 8); if (crc != je32_to_cpu(node.d.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); return; diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index b47ba9f1d606..f193d43a8a59 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.20 2005/10/24 16:22:34 dedekind Exp $ + * $Id: debug.h,v 1.21 2005/11/07 11:14:39 gleixner Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -24,7 +24,7 @@ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS -/* +/* * By defining/undefining the below macros one may select debugging messages * fro specific JFFS2 subsystems. */ @@ -45,7 +45,7 @@ /* Sanity checks are supposed to be light-weight and enabled by default */ #define JFFS2_DBG_SANITY_CHECKS -/* +/* * Dx() are mainly used for debugging messages, they must go away and be * superseded by nicer dbg_xxx() macros... */ @@ -91,7 +91,7 @@ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) - + #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_MSG_PREFIX \ @@ -106,7 +106,7 @@ __FUNCTION__, ##__VA_ARGS__); \ } while(0) -/* +/* * We split our debugging messages on several parts, depending on the JFFS2 * subsystem the message belongs to. */ diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 19bea0f95ac1..a7bf9cb2567f 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.89 2005/09/07 08:34:54 havasi Exp $ + * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $ * */ @@ -64,7 +64,7 @@ struct inode_operations jffs2_dir_inode_operations = /* We keep the dirent list sorted in increasing order of name hash, - and we use the same hash function as the dentries. Makes this + and we use the same hash function as the dentries. Makes this nice and simple */ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, @@ -85,7 +85,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) { - if (fd_list->nhash == target->d_name.hash && + if (fd_list->nhash == target->d_name.hash && (!fd || fd_list->version > fd->version) && strlen(fd_list->name) == target->d_name.len && !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) { @@ -147,7 +147,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) curofs++; /* First loop: curofs = 2; offset = 2 */ if (curofs < offset) { - D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", + D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", fd->name, fd->ino, fd->type, curofs, offset)); continue; } @@ -182,7 +182,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); D1(printk(KERN_DEBUG "jffs2_create()\n")); @@ -203,7 +203,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, f = JFFS2_INODE_INFO(inode); dir_f = JFFS2_INODE_INFO(dir_i); - ret = jffs2_do_create(c, dir_f, f, ri, + ret = jffs2_do_create(c, dir_f, f, ri, dentry->d_name.name, dentry->d_name.len); if (ret) { @@ -234,7 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) int ret; uint32_t now = get_seconds(); - ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, + ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, dead_f, now); if (dead_f->inocache) dentry->d_inode->i_nlink = dead_f->inocache->nlink; @@ -303,11 +303,11 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, @@ -338,7 +338,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -364,7 +364,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char memcpy(f->target, target, targetlen + 1); D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -407,7 +407,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -450,11 +450,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, @@ -482,7 +482,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -494,7 +494,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_clear_inode(inode); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -508,7 +508,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_clear_inode(inode); return ret; } - + rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ @@ -535,9 +535,9 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -599,16 +599,16 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - + if (S_ISBLK(mode) || S_ISCHR(mode)) { dev = cpu_to_je16(old_encode_dev(rdev)); devlen = sizeof(dev); } - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, @@ -638,7 +638,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -650,7 +650,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de jffs2_clear_inode(inode); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -694,9 +694,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -730,7 +730,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, uint8_t type; uint32_t now; - /* The VFS will check for us and prevent trying to rename a + /* The VFS will check for us and prevent trying to rename a * file over a directory and vice versa, but if it's a directory, * the VFS can't check whether the victim is empty. The filesystem * needs to do that for itself. @@ -752,18 +752,18 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, } /* XXX: We probably ought to alloc enough space for - both nodes at the same time. Writing the new link, + both nodes at the same time. Writing the new link, then getting -ENOSPC, is quite bad :) */ /* Make a hard link */ - + /* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; now = get_seconds(); - ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), + ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), old_dentry->d_inode->i_ino, type, new_dentry->d_name.name, new_dentry->d_name.len, now); @@ -782,13 +782,13 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, } } - /* If it was a directory we moved, and there was no victim, + /* If it was a directory we moved, and there was no victim, increase i_nlink on its new parent */ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) new_dir_i->i_nlink++; /* Unlink the original */ - ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); /* We don't touch inode->i_nlink */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 347de4efeeeb..dad68fdffe9e 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -24,7 +24,7 @@ struct erase_priv_struct { struct jffs2_eraseblock *jeb; struct jffs2_sb_info *c; }; - + #ifndef __ECOS static void jffs2_erase_callback(struct erase_info *); #endif @@ -71,7 +71,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, instr->callback = jffs2_erase_callback; instr->priv = (unsigned long)(&instr[1]); instr->fail_addr = 0xffffffff; - + ((struct erase_priv_struct *)instr->priv)->jeb = jeb; ((struct erase_priv_struct *)instr->priv)->c = c; @@ -96,7 +96,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, return; } - if (ret == -EROFS) + if (ret == -EROFS) printk(KERN_WARNING "Erase at 0x%08x failed immediately: -EROFS. Is the sector locked?\n", jeb->offset); else printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); @@ -197,7 +197,7 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock c->nr_erasing_blocks--; spin_unlock(&c->erase_completion_lock); wake_up(&c->erase_wait); -} +} #ifndef __ECOS static void jffs2_erase_callback(struct erase_info *instr) @@ -209,7 +209,7 @@ static void jffs2_erase_callback(struct erase_info *instr) jffs2_erase_failed(priv->c, priv->jeb, instr->fail_addr); } else { jffs2_erase_succeeded(priv->c, priv->jeb); - } + } kfree(instr); } #endif /* !__ECOS */ @@ -227,13 +227,13 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, /* Walk the inode's list once, removing any nodes from this eraseblock */ while (1) { if (!(*prev)->next_in_ino) { - /* We're looking at the jffs2_inode_cache, which is + /* We're looking at the jffs2_inode_cache, which is at the end of the linked list. Stash it and continue from the beginning of the list */ ic = (struct jffs2_inode_cache *)(*prev); prev = &ic->nodes; continue; - } + } if (SECTOR_ADDR((*prev)->flash_offset) == jeb->offset) { /* It's in the block we're erasing */ @@ -267,7 +267,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); this = ic->nodes; - + while(this) { printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); if (++i == 5) { @@ -290,7 +290,7 @@ static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_erase while(jeb->first_node) { ref = jeb->first_node; jeb->first_node = ref->next_phys; - + /* Remove from the inode-list */ if (ref->next_in_ino) jffs2_remove_node_refs_from_ino_list(c, ref, jeb); @@ -307,7 +307,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl uint32_t ofs; size_t retlen; int ret = -EIO; - + ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!ebuf) { printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset); @@ -361,7 +361,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb case -EIO: goto filebad; } - /* Write the erase complete marker */ + /* Write the erase complete marker */ D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); bad_offset = jeb->offset; @@ -399,7 +399,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb vecs[0].iov_base = (unsigned char *) ▮ vecs[0].iov_len = sizeof(marker); ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen); - + if (ret || retlen != sizeof(marker)) { if (ret) printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", @@ -416,9 +416,9 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb marker_ref->next_phys = NULL; marker_ref->flash_offset = jeb->offset | REF_NORMAL; marker_ref->__totlen = c->cleanmarker_size; - + jeb->first_node = jeb->last_node = marker_ref; - + jeb->free_size = c->sector_size - c->cleanmarker_size; jeb->used_size = c->cleanmarker_size; jeb->dirty_size = 0; diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 605ea6b0b473..935f273dc57b 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -34,8 +34,8 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) /* Trigger GC to flush any pending writes for this inode */ jffs2_flush_wbuf_gc(c, inode->i_ino); - - return 0; + + return 0; } struct file_operations jffs2_file_operations = @@ -107,7 +107,7 @@ static int jffs2_readpage (struct file *filp, struct page *pg) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host); int ret; - + down(&f->sem); ret = jffs2_do_readpage_unlock(pg->mapping->host, pg); up(&f->sem); @@ -130,7 +130,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; uint32_t phys_ofs, alloc_len; - + D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); @@ -160,7 +160,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ri.compr = JFFS2_COMPR_ZERO; ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(0); - + fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); if (IS_ERR(fn)) { @@ -187,7 +187,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, inode->i_size = pageofs; up(&f->sem); } - + /* Read in the page if it wasn't already present, unless it's a whole page */ if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { down(&f->sem); @@ -218,7 +218,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (!start && end == PAGE_CACHE_SIZE) { /* We need to avoid deadlock with page_cache_read() in jffs2_garbage_collect_pass(). So we have to mark the - page up to date, to prevent page_cache_read() from + page up to date, to prevent page_cache_read() from trying to re-lock it. */ SetPageUptodate(pg); } @@ -252,7 +252,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, /* There was an error writing. */ SetPageError(pg); } - + /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ if (writtenlen < (start&3)) writtenlen = 0; @@ -263,7 +263,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; inode->i_blocks = (inode->i_size + 511) >> 9; - + inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); } } @@ -272,7 +272,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (start+writtenlen < end) { /* generic_file_write has written more to the page cache than we've - actually written to the medium. Mark the page !Uptodate so that + actually written to the medium. Mark the page !Uptodate so that it gets reread */ D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n")); SetPageError(pg); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index b0b96d7272d8..543420665c5b 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -40,7 +40,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) int ret; D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); ret = inode_change_ok(inode, iattr); - if (ret) + if (ret) return ret; /* Special cases - we don't want more than one data node @@ -73,7 +73,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) kfree(mdata); return -ENOMEM; } - + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -84,7 +84,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) } down(&f->sem); ivalid = iattr->ia_valid; - + ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); @@ -100,7 +100,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) if (iattr->ia_mode & S_ISGID && !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID); - else + else ri->mode = cpu_to_jemode(iattr->ia_mode); else ri->mode = cpu_to_jemode(inode->i_mode); @@ -129,7 +129,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); if (S_ISLNK(inode->i_mode)) kfree(mdata); - + if (IS_ERR(new_metadata)) { jffs2_complete_reservation(c); jffs2_free_raw_inode(ri); @@ -167,7 +167,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) jffs2_complete_reservation(c); /* We have to do the vmtruncate() without f->sem held, since - some pages may be locked and waiting for it in readpage(). + some pages may be locked and waiting for it in readpage(). We are protected from a simultaneous write() extending i_size back past iattr->ia_size, because do_truncate() holds the generic inode semaphore. */ @@ -210,12 +210,12 @@ int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) void jffs2_clear_inode (struct inode *inode) { - /* We can forget about this inode for now - drop all + /* We can forget about this inode for now - drop all * the nodelists associated with it, etc. */ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - + D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); jffs2_do_clear_inode(c, f); @@ -234,7 +234,7 @@ void jffs2_read_inode (struct inode *inode) c = JFFS2_SB_INFO(inode->i_sb); jffs2_init_inode_info(f); - + ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); if (ret) { @@ -254,14 +254,14 @@ void jffs2_read_inode (struct inode *inode) inode->i_blksize = PAGE_SIZE; inode->i_blocks = (inode->i_size + 511) >> 9; - + switch (inode->i_mode & S_IFMT) { jint16_t rdev; case S_IFLNK: inode->i_op = &jffs2_symlink_inode_operations; break; - + case S_IFDIR: { struct jffs2_full_dirent *fd; @@ -298,7 +298,7 @@ void jffs2_read_inode (struct inode *inode) jffs2_do_clear_inode(c, f); make_bad_inode(inode); return; - } + } case S_IFSOCK: case S_IFIFO: @@ -354,11 +354,11 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); up(&c->alloc_sem); - } + } if (!(*flags & MS_RDONLY)) jffs2_start_garbage_collect_thread(c); - + *flags |= MS_NOATIME; return 0; @@ -392,9 +392,9 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); c = JFFS2_SB_INFO(sb); - + inode = new_inode(sb); - + if (!inode) return ERR_PTR(-ENOMEM); @@ -458,14 +458,14 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) #endif c->flash_size = c->mtd->size; - c->sector_size = c->mtd->erasesize; + c->sector_size = c->mtd->erasesize; blocks = c->flash_size / c->sector_size; /* * Size alignment check */ if ((c->sector_size * blocks) != c->flash_size) { - c->flash_size = c->sector_size * blocks; + c->flash_size = c->sector_size * blocks; printk(KERN_INFO "jffs2: Flash size not aligned to erasesize, reducing to %dKiB\n", c->flash_size / 1024); } @@ -543,16 +543,16 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic; if (!nlink) { /* The inode has zero nlink but its nodes weren't yet marked - obsolete. This has to be because we're still waiting for + obsolete. This has to be because we're still waiting for the final (close() and) iput() to happen. - There's a possibility that the final iput() could have + There's a possibility that the final iput() could have happened while we were contemplating. In order to ensure that we don't cause a new read_inode() (which would fail) for the inode in question, we use ilookup() in this case instead of iget(). - The nlink can't _become_ zero at this point because we're + The nlink can't _become_ zero at this point because we're holding the alloc_sem, and jffs2_do_unlink() would also need that while decrementing nlink on any inode. */ @@ -599,19 +599,19 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, return JFFS2_INODE_INFO(inode); } -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, +unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv) { struct inode *inode = OFNI_EDONI_2SFFJ(f); struct page *pg; - pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); if (IS_ERR(pg)) return (void *)pg; - + *priv = (unsigned long)pg; return kmap(pg); } @@ -628,7 +628,7 @@ void jffs2_gc_release_page(struct jffs2_sb_info *c, static int jffs2_flash_setup(struct jffs2_sb_info *c) { int ret = 0; - + if (jffs2_cleanmarker_oob(c)) { /* NAND flash... do setup accordingly */ ret = jffs2_nand_flash_setup(c); @@ -642,7 +642,7 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) { if (ret) return ret; } - + /* and Dataflash */ if (jffs2_dataflash(c)) { ret = jffs2_dataflash_setup(c); @@ -670,7 +670,7 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) { if (jffs2_nor_ecc(c)) { jffs2_nor_ecc_flash_cleanup(c); } - + /* and DataFlash */ if (jffs2_dataflash(c)) { jffs2_dataflash_cleanup(c); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index ee54cdc59e06..f9ffece453a3 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.154 2005/09/07 08:34:54 havasi Exp $ + * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $ * */ @@ -21,14 +21,14 @@ #include "nodelist.h" #include "compr.h" -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, +static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_raw_node_ref *raw); -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, @@ -55,7 +55,7 @@ again: D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); nextlist = &c->bad_used_list; } else if (n < 50 && !list_empty(&c->erasable_list)) { - /* Note that most of them will have gone directly to be erased. + /* Note that most of them will have gone directly to be erased. So don't favour the erasable_list _too_ much. */ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); nextlist = &c->erasable_list; @@ -101,7 +101,7 @@ again: printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); BUG(); } - + /* Have we accidentally picked a clean block with wasted space ? */ if (ret->wasted_size) { D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); @@ -136,7 +136,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) /* We can't start doing GC yet. We haven't finished checking the node CRCs etc. Do it now. */ - + /* checked_ino is protected by the alloc_sem */ if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", @@ -178,7 +178,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) case INO_STATE_READING: /* We need to wait for it to finish, lest we move on - and trigger the BUG() above while we haven't yet + and trigger the BUG() above while we haven't yet finished checking all its nodes */ D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); up(&c->alloc_sem); @@ -228,13 +228,13 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) } raw = jeb->gc_node; - + while(ref_obsolete(raw)) { D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); raw = raw->next_phys; if (unlikely(!raw)) { printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); - printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", + printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); jeb->gc_node = raw; spin_unlock(&c->erase_completion_lock); @@ -259,7 +259,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ic = jffs2_raw_ref_to_ic(raw); /* We need to hold the inocache. Either the erase_completion_lock or - the inocache_lock are sufficient; we trade down since the inocache_lock + the inocache_lock are sufficient; we trade down since the inocache_lock causes less contention. */ spin_lock(&c->inocache_lock); @@ -278,14 +278,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) switch(ic->state) { case INO_STATE_CHECKEDABSENT: - /* It's been checked, but it's not currently in-core. + /* It's been checked, but it's not currently in-core. We can just copy any pristine nodes, but have to prevent anyone else from doing read_inode() while we're at it, so we set the state accordingly */ if (ref_flags(raw) == REF_PRISTINE) ic->state = INO_STATE_GC; else { - D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", + D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", ic->ino)); } break; @@ -298,8 +298,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) case INO_STATE_CHECKING: case INO_STATE_GC: /* Should never happen. We should have finished checking - by the time we actually start doing any GC, and since - we're holding the alloc_sem, no other garbage collection + by the time we actually start doing any GC, and since + we're holding the alloc_sem, no other garbage collection can happen. */ printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", @@ -319,21 +319,21 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", ic->ino, ic->state)); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - /* And because we dropped the alloc_sem we must start again from the + /* And because we dropped the alloc_sem we must start again from the beginning. Ponder chance of livelock here -- we're returning success without actually making any progress. - Q: What are the chances that the inode is back in INO_STATE_READING + Q: What are the chances that the inode is back in INO_STATE_READING again by the time we next enter this function? And that this happens enough times to cause a real delay? - A: Small enough that I don't care :) + A: Small enough that I don't care :) */ return 0; } /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the - node intact, and we don't have to muck about with the fragtree etc. + node intact, and we don't have to muck about with the fragtree etc. because we know it's not in-core. If it _was_ in-core, we go through all the iget() crap anyway */ @@ -453,7 +453,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era if (!ret) { /* Urgh. Return it sensibly. */ frag->node->raw = f->inocache->nodes; - } + } if (ret != -EBADFD) goto upnout; } @@ -467,7 +467,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era } goto upnout; } - + /* Wasn't a dnode. Try dirent */ for (fd = f->dents; fd; fd=fd->next) { if (fd->raw == raw) @@ -494,7 +494,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era return ret; } -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, +static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_raw_node_ref *raw) { @@ -580,7 +580,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, } break; default: - printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", + printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", ref_offset(raw), je16_to_cpu(node->u.nodetype)); goto bail; } @@ -621,7 +621,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, retried = 1; D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); - + jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -669,7 +669,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto out_node; } -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) { struct jffs2_full_dnode *new_fn; @@ -684,7 +684,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ S_ISCHR(JFFS2_F_I_MODE(f)) ) { /* For these, we don't actually need to read the old node */ /* FIXME: for minor or major > 255. */ - dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | + dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | JFFS2_F_I_RDEV_MIN(f))); mdata = (char *)&dev; mdatalen = sizeof(dev); @@ -705,7 +705,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bites of symlink target\n", mdatalen)); } - + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -713,7 +713,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ sizeof(ri)+ mdatalen, ret); goto out; } - + last_frag = frag_last(&f->fragtree); if (last_frag) /* Fetch the inode length from the fragtree rather then @@ -721,7 +721,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ ilen = last_frag->ofs + last_frag->size; else ilen = JFFS2_F_I_SIZE(f); - + memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); @@ -760,7 +760,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ return ret; } -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) { struct jffs2_full_dirent *new_fd; @@ -781,12 +781,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er so refrain from splatting them. */ if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f)) rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f)); - else + else rd.mctime = cpu_to_je32(0); rd.type = fd->type; rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { @@ -804,7 +804,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er return 0; } -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) { struct jffs2_full_dirent **fdp = &f->dents; @@ -843,7 +843,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct if (ref_totlen(c, NULL, raw) != rawlen) continue; - /* Doesn't matter if there's one in the same erase block. We're going to + /* Doesn't matter if there's one in the same erase block. We're going to delete it too at the same time. */ if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset)) continue; @@ -895,7 +895,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct kfree(rd); } - /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, + /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, we should update the metadata node with those times accordingly */ /* No need for it any more. Just mark it obsolete and remove it from the list */ @@ -927,13 +927,13 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", f->inocache->ino, start, end)); - + memset(&ri, 0, sizeof(ri)); if(fn->frags > 1) { size_t readlen; uint32_t crc; - /* It's partially obsoleted by a later write. So we have to + /* It's partially obsoleted by a later write. So we have to write it out again with the _same_ version as before */ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); if (readlen != sizeof(ri) || ret) { @@ -955,16 +955,16 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras crc = crc32(0, &ri, sizeof(ri)-8); if (crc != je32_to_cpu(ri.node_crc)) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", - ref_offset(fn->raw), + ref_offset(fn->raw), je32_to_cpu(ri.node_crc), crc); /* FIXME: We could possibly deal with this by writing new holes for each frag */ - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", + printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } if (ri.compr != JFFS2_COMPR_ZERO) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", + printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } @@ -982,7 +982,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.csize = cpu_to_je32(0); ri.compr = JFFS2_COMPR_ZERO; } - + frag = frag_last(&f->fragtree); if (frag) /* Fetch the inode length from the fragtree rather then @@ -1024,10 +1024,10 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras return 0; } - /* + /* * We should only get here in the case where the node we are * replacing had more than one frag, so we kept the same version - * number as before. (Except in case of error -- see 'goto fill;' + * number as before. (Except in case of error -- see 'goto fill;' * above.) */ D1(if(unlikely(fn->frags <= 1)) { @@ -1039,7 +1039,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ mark_ref_normal(new_fn->raw); - for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); + for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); frag; frag = frag_next(frag)) { if (frag->ofs > fn->size + fn->ofs) break; @@ -1057,10 +1057,10 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras printk(KERN_WARNING "jffs2_garbage_collect_hole: New node has no frags!\n"); BUG(); } - + jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); - + return 0; } @@ -1070,12 +1070,12 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era { struct jffs2_full_dnode *new_fn; struct jffs2_raw_inode ri; - uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; + uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; int ret = 0; unsigned char *comprbuf = NULL, *writebuf; unsigned long pg; unsigned char *pg_ptr; - + memset(&ri, 0, sizeof(ri)); D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", @@ -1087,8 +1087,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { /* Attempt to do some merging. But only expand to cover logically adjacent frags if the block containing them is already considered - to be dirty. Otherwise we end up with GC just going round in - circles dirtying the nodes it already wrote out, especially + to be dirty. Otherwise we end up with GC just going round in + circles dirtying the nodes it already wrote out, especially on NAND where we have small eraseblocks and hence a much higher chance of nodes having to be split to cross boundaries. */ @@ -1122,7 +1122,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } else { - /* OK, it's a frag which extends to the beginning of the page. Does it live + /* OK, it's a frag which extends to the beginning of the page. Does it live in a block which is still considered clean? If so, don't obsolete it. If not, cover it anyway. */ @@ -1172,7 +1172,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } else { - /* OK, it's a frag which extends to the beginning of the page. Does it live + /* OK, it's a frag which extends to the beginning of the page. Does it live in a block which is still considered clean? If so, don't obsolete it. If not, cover it anyway. */ @@ -1199,14 +1199,14 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } } - D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", + D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", orig_start, orig_end, start, end)); D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size)); BUG_ON(end < orig_end); BUG_ON(start > orig_start); } - + /* First, use readpage() to read the appropriate page into the page cache */ /* Q: What happens if we actually try to GC the _same_ page for which commit_write() * triggered garbage collection in the first place? @@ -1263,7 +1263,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era ri.usercompr = (comprtype >> 8) & 0xff; ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - + new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); jffs2_free_comprbuf(comprbuf, writebuf); diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h index 84f184f0836f..22a93a08210c 100644 --- a/fs/jffs2/histo.h +++ b/fs/jffs2/histo.h @@ -1,3 +1,3 @@ /* This file provides the bit-probabilities for the input file */ -#define BIT_DIVIDER 629 +#define BIT_DIVIDER 629 static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */ diff --git a/fs/jffs2/histo_mips.h b/fs/jffs2/histo_mips.h index 9a443268d885..fa3dac19a109 100644 --- a/fs/jffs2/histo_mips.h +++ b/fs/jffs2/histo_mips.h @@ -1,2 +1,2 @@ -#define BIT_DIVIDER_MIPS 1043 +#define BIT_DIVIDER_MIPS 1043 static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c index 238c7992064c..69099835de1c 100644 --- a/fs/jffs2/ioctl.c +++ b/fs/jffs2/ioctl.c @@ -7,17 +7,17 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: ioctl.c,v 1.9 2004/11/16 20:36:11 dwmw2 Exp $ + * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $ * */ #include -int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { /* Later, this will provide for lsattr.jffs2 and chattr.jffs2, which will include compression support etc. */ return -ENOTTY; } - + diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index f27df015f3ec..036cbd11c004 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.30 2005/09/20 14:27:34 dedekind Exp $ + * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $ * */ @@ -29,7 +29,7 @@ static kmem_cache_t *inode_cache_slab; int __init jffs2_create_slab_caches(void) { - full_dnode_slab = kmem_cache_create("jffs2_full_dnode", + full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), 0, 0, NULL, NULL); if (!full_dnode_slab) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 80fe8feffb4d..c79eebb8ab32 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.114 2005/09/21 13:28:35 dedekind Exp $ + * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $ * */ @@ -24,7 +24,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) { struct jffs2_full_dirent **prev = list; - + dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { @@ -75,14 +75,14 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint if (size == 0) return; - /* + /* * If the last fragment starts at the RAM page boundary, it is * REF_PRISTINE irrespective of its size. */ frag = frag_last(list); if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", - frag->ofs, frag->ofs + frag->size); + frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } } @@ -102,7 +102,7 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } - + } jffs2_free_node_frag(this); } @@ -117,7 +117,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ while (*link) { parent = *link; base = rb_entry(parent, struct jffs2_node_frag, rb); - + if (newfrag->ofs > base->ofs) link = &base->rb.rb_right; else if (newfrag->ofs < base->ofs) @@ -137,7 +137,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) { struct jffs2_node_frag *newfrag; - + newfrag = jffs2_alloc_node_frag(); if (likely(newfrag)) { newfrag->ofs = ofs; @@ -169,7 +169,7 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, } if (this) { - /* By definition, the 'this' node has no right-hand child, + /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n", @@ -183,13 +183,13 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, rb_insert_color(&holefrag->rb, root); this = holefrag; } - + if (this) { - /* By definition, the 'this' node has no right-hand child, + /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ dbg_fragtree2("add the new node at the right\n"); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { dbg_fragtree2("insert the new node at the root of the tree\n"); rb_link_node(&newfrag->rb, NULL, &root->rb_node); @@ -216,7 +216,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r dbg_fragtree2("lookup gave no frag\n"); lastend = 0; } - + /* See if we ran off the end of the fragtree */ if (lastend <= newfrag->ofs) { /* We did */ @@ -243,7 +243,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, - * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs + * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs */ if (newfrag->ofs > this->ofs) { /* This node isn't completely obsoleted. The start of it remains valid */ @@ -261,10 +261,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r if (this->node) dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); - else + else dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n", this->ofs, this->ofs+this->size); - + /* New second frag pointing to this's node */ newfrag2 = new_fragment(this->node, newfrag->ofs + newfrag->size, this->ofs + this->size - newfrag->ofs - newfrag->size); @@ -284,10 +284,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r from newfrag to insert newfrag2. */ jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); - + jffs2_fragtree_insert(newfrag2, newfrag); rb_insert_color(&newfrag2->rb, root); - + return 0; } /* New node just reduces 'this' frag in size, doesn't split it */ @@ -297,13 +297,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); } else { - /* New frag starts at the same point as 'this' used to. Replace + /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); - + rb_replace_node(&this->rb, &newfrag->rb, root); - + if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); @@ -317,7 +317,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } } /* OK, now we have newfrag added in the correct place in the tree, but - frag_next(newfrag) may be a fragment which is overlapped by it + frag_next(newfrag) may be a fragment which is overlapped by it */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ @@ -326,7 +326,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); } - /* Now we're pointing at the first frag which isn't totally obsoleted by + /* Now we're pointing at the first frag which isn't totally obsoleted by the new frag */ if (!this || newfrag->ofs + newfrag->size == this->ofs) @@ -344,7 +344,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r return 0; } -/* +/* * Given an inode, probably with existing tree of fragments, add the new node * to the fragment tree. */ @@ -363,7 +363,7 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); - + ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); if (unlikely(ret)) return ret; @@ -374,14 +374,14 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in struct jffs2_node_frag *prev = frag_prev(newfrag); mark_ref_normal(fn->raw); - /* If we don't start at zero there's _always_ a previous */ + /* If we don't start at zero there's _always_ a previous */ if (prev->node) mark_ref_normal(prev->node->raw); } if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { struct jffs2_node_frag *next = frag_next(newfrag); - + if (next) { mark_ref_normal(fn->raw); if (next->node) @@ -412,7 +412,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info if (!jffs2_is_writebuffered(c)) goto adj_acc; - + /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); len = ofs % c->wbuf_pagesize; @@ -424,13 +424,13 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info ref_offset(ref), tn->csize, ofs); goto adj_acc; } - + ofs += len; len = tn->csize - len; - + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); - + #ifndef __ECOS /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), * adding and jffs2_flash_read_end() interface. */ @@ -445,12 +445,12 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info pointed = 1; /* succefully pointed to device */ } #endif - + if (!pointed) { buffer = kmalloc(len, GFP_KERNEL); if (unlikely(!buffer)) return -ENOMEM; - + /* TODO: this is very frequent pattern, make it a separate * routine */ err = jffs2_flash_read(c, ofs, len, &retlen, buffer); @@ -458,7 +458,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); goto free_out; } - + if (retlen != len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ofs, retlen, len); err = -EIO; @@ -485,7 +485,7 @@ adj_acc: jeb = &c->blocks[ref->flash_offset / c->sector_size]; len = ref_totlen(c, jeb, ref); - /* + /* * Mark the node as having been checked and fix the * accounting accordingly. */ @@ -516,13 +516,13 @@ free_out: static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) { int ret; - + BUG_ON(ref_obsolete(tn->fn->raw)); /* We only check the data CRC of unchecked nodes */ if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - + dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); @@ -538,7 +538,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f return ret; } -/* +/* * Helper function for jffs2_add_older_frag_to_fragtree(). * * Called when the new fragment that is being inserted @@ -551,31 +551,31 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); if (hole->ofs == newfrag->ofs) { - /* + /* * Well, the new fragment actually starts at the same offset as * the hole. */ if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { - /* + /* * We replace the overlapped left part of the hole by * the new node. */ - + dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); - + hole->ofs += newfrag->size; hole->size -= newfrag->size; - - /* + + /* * We know that 'hole' should be the right hand * fragment. */ jffs2_fragtree_insert(hole, newfrag); rb_insert_color(&hole->rb, root); } else { - /* + /* * Ah, the new fragment is of the same size as the hole. * Relace the hole by it. */ @@ -586,7 +586,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, } } else { /* The new fragment lefts some hole space at the left */ - + struct jffs2_node_frag * newfrag2 = NULL; if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { @@ -606,7 +606,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, jffs2_fragtree_insert(newfrag, hole); rb_insert_color(&newfrag->rb, root); - + if (newfrag2) { dbg_fragtree2("left the hole %#04x-%#04x at the right\n", newfrag2->ofs, newfrag2->ofs + newfrag2->size); @@ -654,18 +654,18 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode lastend = this->ofs + this->size; else lastend = 0; - + /* Detect the preliminary type of node */ if (fn->size >= PAGE_CACHE_SIZE) ref_flag = REF_PRISTINE; else ref_flag = REF_NORMAL; - + /* See if we ran off the end of the root */ if (lastend <= fn_ofs) { /* We did */ - - /* + + /* * We are going to insert the new node into the * fragment tree, so check it. */ @@ -691,21 +691,21 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode fn->frags = 0; while (1) { - /* + /* * Here we have: * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs. - * + * * Remember, 'this' has higher version, any non-hole node * which is already in the fragtree is newer then the newly * inserted. */ if (!this->node) { - /* + /* * 'this' is the hole fragment, so at least the * beginning of the new fragment is valid. */ - - /* + + /* * We are going to insert the new node into the * fragment tree, so check it. */ @@ -715,7 +715,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode return err; checked = 1; } - + if (this->ofs + this->size >= fn_ofs + fn_size) { /* We split the hole on two parts */ @@ -730,7 +730,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode goto out_ok; } - /* + /* * The beginning of the new fragment is valid since it * overlaps the hole node. */ @@ -742,9 +742,9 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this->ofs + this->size - fn_ofs); if (unlikely(!newfrag)) return -ENOMEM; - + if (fn_ofs == this->ofs) { - /* + /* * The new node starts at the same offset as * the hole and supersieds the hole. */ @@ -754,21 +754,21 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode rb_replace_node(&this->rb, &newfrag->rb, root); jffs2_free_node_frag(this); } else { - /* + /* * The hole becomes shorter as its right part * is supersieded by the new fragment. */ dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - + dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); - + this->size -= newfrag->size; jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); } - + fn_ofs += newfrag->size; fn_size -= newfrag->size; this = rb_entry(rb_next(&newfrag->rb), @@ -778,7 +778,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } - /* + /* * 'This' node is not the hole so it obsoletes the new fragment * either fully or partially. */ @@ -791,19 +791,19 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode goto out_ok; } else { struct jffs2_node_frag *new_this; - + /* 'This' node obsoletes the beginning of the new node */ dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); ref_flag = REF_NORMAL; - + fn_size -= this->ofs + this->size - fn_ofs; fn_ofs = this->ofs + this->size; dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); - + new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); if (!new_this) { - /* + /* * There is no next fragment. Add the rest of * the new node as the right-hand child. */ @@ -813,7 +813,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode return err; checked = 1; } - + fn->frags += 1; newfrag = new_fragment(fn, fn_ofs, fn_size); if (unlikely(!newfrag)) @@ -821,7 +821,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); rb_insert_color(&newfrag->rb, root); goto out_ok; } else { @@ -862,9 +862,9 @@ void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache /* During mount, this needs no locking. During normal operation, its callers want to do other stuff while still holding the inocache_lock. - Rather than introducing special case get_ino_cache functions or + Rather than introducing special case get_ino_cache functions or callbacks, we just let the caller do the locking itself. */ - + struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ret; @@ -873,7 +873,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t while (ret && ret->ino < ino) { ret = ret->next; } - + if (ret && ret->ino != ino) ret = NULL; @@ -907,9 +907,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); - + prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; - + while ((*prev) && (*prev)->ino < old->ino) { prev = &(*prev)->next; } @@ -919,7 +919,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) /* Free it now unless it's in READING or CLEARING state, which are the transitions upon read_inode() and clear_inode(). The - rest of the time we know nobody else is looking at it, and + rest of the time we know nobody else is looking at it, and if it's held by read_inode() or clear_inode() they'll free it for themselves. */ if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING) @@ -932,7 +932,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) { int i; struct jffs2_inode_cache *this, *next; - + for (i=0; iinocache_list[i]; while (this) { @@ -959,10 +959,10 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) c->blocks[i].first_node = c->blocks[i].last_node = NULL; } } - + struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) { - /* The common case in lookup is that there will be a node + /* The common case in lookup is that there will be a node which precisely matches. So we go looking for that first */ struct rb_node *next; struct jffs2_node_frag *prev = NULL; @@ -993,9 +993,9 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ if (prev) dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n", prev->ofs, prev->ofs+prev->size); - else + else dbg_fragtree2("returning NULL, empty fragtree\n"); - + return prev; } @@ -1010,7 +1010,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) return; dbg_fragtree("killing\n"); - + frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { if (frag->rb.rb_left) { @@ -1023,18 +1023,18 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) } if (frag->node && !(--frag->node->frags)) { - /* Not a hole, and it's the final remaining frag + /* Not a hole, and it's the final remaining frag of this node. Free the node */ if (c) jffs2_mark_node_obsolete(c, frag->node->raw); - + jffs2_free_full_dnode(frag->node); } parent = frag_parent(frag); if (parent) { if (frag_left(parent) == frag) parent->rb.rb_left = NULL; - else + else parent->rb.rb_right = NULL; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1222372cb290..23a67bb3052f 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -58,7 +58,7 @@ #define je16_to_cpu(x) (le16_to_cpu(x.v16)) #define je32_to_cpu(x) (le32_to_cpu(x.v32)) #define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) -#else +#else #error wibble #endif @@ -68,7 +68,7 @@ /* This is all we need to keep in-core for each raw node during normal operation. As and when we do read_inode on a particular inode, we can - scan the nodes which are listed for it and build up a proper map of + scan the nodes which are listed for it and build up a proper map of which nodes are currently valid. JFFSv1 always used to keep that whole map in core for each inode. */ @@ -85,7 +85,7 @@ struct jffs2_raw_node_ref /* flash_offset & 3 always has to be zero, because nodes are always aligned at 4 bytes. So we have a couple of extra bits - to play with, which indicate the node's status; see below: */ + to play with, which indicate the node's status; see below: */ #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ #define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ #define REF_PRISTINE 2 /* Completely clean. GC without looking */ @@ -98,7 +98,7 @@ struct jffs2_raw_node_ref /* For each inode in the filesystem, we need to keep a record of nlink, because it would be a PITA to scan the whole directory tree at read_inode() time to calculate it, and to keep sufficient information - in the raw_node_ref (basically both parent and child inode number for + in the raw_node_ref (basically both parent and child inode number for dirent nodes) would take more space than this does. We also keep a pointer to the first physical node which is part of this inode, too. */ @@ -128,7 +128,7 @@ struct jffs2_inode_cache { #define INOCACHE_HASHSIZE 128 /* - Larger representation of a raw node, kept in-core only when the + Larger representation of a raw node, kept in-core only when the struct inode for this particular ino is instantiated. */ @@ -138,11 +138,11 @@ struct jffs2_full_dnode uint32_t ofs; /* The offset to which the data of this node belongs */ uint32_t size; uint32_t frags; /* Number of fragments which currently refer - to this node. When this reaches zero, + to this node. When this reaches zero, the node is obsolete. */ }; -/* +/* Even larger representation of a raw node, kept in-core only while we're actually building up the original map of which nodes go where, in read_inode() @@ -155,7 +155,7 @@ struct jffs2_tmp_dnode_info uint32_t data_crc; uint32_t partial_crc; uint32_t csize; -}; +}; struct jffs2_full_dirent { @@ -169,7 +169,7 @@ struct jffs2_full_dirent }; /* - Fragments - used to build a map of which raw node to obtain + Fragments - used to build a map of which raw node to obtain data from for each part of the ino */ struct jffs2_node_frag @@ -209,7 +209,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) { uint32_t ref_end; - + if (ref->next_phys) ref_end = ref_offset(ref->next_phys); else { @@ -264,7 +264,7 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, #define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) /* check if dirty space is more than 255 Byte */ -#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) +#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) #define PAD(x) (((x)+3)&~3) @@ -341,7 +341,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, + struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen); int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); @@ -349,7 +349,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 2c938d1bffb0..49127a1f0458 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -88,12 +88,12 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs up(&c->alloc_sem); return -ENOSPC; } - + /* Calc possibly available space. Possibly available means that we * don't know, if unchecked size contains obsoleted nodes, which could give us some * more usable space. This will affect the sum only once, as gc first finishes checking * of nodes. - + Return -ENOSPC, if the maximum possibly available space is less or equal than + + Return -ENOSPC, if the maximum possibly available space is less or equal than * blocksneeded * sector_size. * This blocks endless gc looping on a filesystem, which is nearly full, even if * the check above passes. @@ -118,7 +118,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); spin_unlock(&c->erase_completion_lock); - + ret = jffs2_garbage_collect_pass(c); if (ret) return ret; @@ -183,7 +183,7 @@ static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblo jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); list_add_tail(&jeb->list, &c->dirty_list); } - } else { + } else { D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); list_add_tail(&jeb->list, &c->clean_list); @@ -197,7 +197,7 @@ static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblo static int jffs2_find_nextblock(struct jffs2_sb_info *c) { struct list_head *next; - + /* Take the next block off the 'free' list */ if (list_empty(&c->free_list)) { @@ -229,8 +229,8 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) if (!c->nr_erasing_blocks) { /* Ouch. We're in GC, or we wouldn't have got here. And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", + printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", + c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); return -ENOSPC; } @@ -250,7 +250,7 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) list_del(next); c->nextblock = list_entry(next, struct jffs2_eraseblock, list); c->nr_free_blocks--; - + jffs2_sum_reset_collected(c->summary); /* reset collected summary */ D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); @@ -354,9 +354,9 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { - /* Only node in it beforehand was a CLEANMARKER node (we think). + /* Only node in it beforehand was a CLEANMARKER node (we think). So mark it obsolete now that there's going to be another node - in the block. This will reduce used_size to zero but We've + in the block. This will reduce used_size to zero but We've already set c->nextblock so that jffs2_mark_node_obsolete() won't try to refile it to the dirty_list. */ @@ -376,12 +376,12 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin * @len: length of this physical node * @dirty: dirty flag for new node * - * Should only be used to report nodes for which space has been allocated + * Should only be used to report nodes for which space has been allocated * by jffs2_reserve_space. * * Must be called with the alloc_sem held. */ - + int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) { struct jffs2_eraseblock *jeb; @@ -488,8 +488,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) && !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) { - /* Hm. This may confuse static lock analysis. If any of the above - three conditions is false, we're going to return from this + /* Hm. This may confuse static lock analysis. If any of the above + three conditions is false, we're going to return from this function without actually obliterating any nodes or freeing any jffs2_raw_node_refs. So we don't need to stop erases from happening, or protect against people holding an obsolete @@ -546,17 +546,17 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref D1(printk(KERN_DEBUG "Wasting\n")); addedsize = 0; jeb->wasted_size += ref_totlen(c, jeb, ref); - c->wasted_size += ref_totlen(c, jeb, ref); + c->wasted_size += ref_totlen(c, jeb, ref); } ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - + jffs2_dbg_acct_sanity_check_nolock(c, jeb); jffs2_dbg_acct_paranoia_check_nolock(c, jeb); if (c->flags & JFFS2_SB_FLAG_SCANNING) { /* Flash scanning is in progress. Don't muck about with the block lists because they're not ready yet, and don't actually - obliterate nodes that look obsolete. If they weren't + obliterate nodes that look obsolete. If they weren't marked obsolete on the flash at the time they _became_ obsolete, there was probably a reason for that. */ spin_unlock(&c->erase_completion_lock); @@ -590,7 +590,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref immediately reused, and we spread the load a bit. */ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); list_add_tail(&jeb->list, &c->erasable_list); - } + } } D1(printk(KERN_DEBUG "Done OK\n")); } else if (jeb == c->gcblock) { @@ -608,8 +608,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref list_add_tail(&jeb->list, &c->very_dirty_list); } else { D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - } + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + } spin_unlock(&c->erase_completion_lock); @@ -656,11 +656,11 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* Nodes which have been marked obsolete no longer need to be associated with any inode. Remove them from the per-inode list. - - Note we can't do this for NAND at the moment because we need + + Note we can't do this for NAND at the moment because we need obsolete dirent nodes to stay on the lists, because of the horridness in jffs2_garbage_collect_deletion_dirent(). Also - because we delete the inocache, and on NAND we need that to + because we delete the inocache, and on NAND we need that to stay around until all the nodes are actually erased, in order to stop us from giving the same inode number to another newly created inode. */ @@ -689,7 +689,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (ref->next_phys && ref_obsolete(ref->next_phys) && !ref->next_phys->next_in_ino) { struct jffs2_raw_node_ref *n = ref->next_phys; - + spin_lock(&c->erase_completion_lock); ref->__totlen += n->__totlen; @@ -703,7 +703,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref jffs2_free_raw_node_ref(n); } - + /* Also merge with the previous node in the list, if there is one and that one is obsolete */ if (ref != jeb->first_node ) { @@ -713,7 +713,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref while (p->next_phys != ref) p = p->next_phys; - + if (ref_obsolete(p) && !ref->next_in_ino) { p->__totlen += ref->__totlen; if (jeb->last_node == ref) { @@ -753,11 +753,11 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) */ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size; - if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && - (dirty > c->nospc_dirty_size)) + if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && + (dirty > c->nospc_dirty_size)) ret = 1; - D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", + D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); return ret; diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 04d4167ab252..59e7a393200c 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -191,18 +191,18 @@ void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int nlink); -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, +unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv); void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv); void jffs2_flash_cleanup(struct jffs2_sb_info *c); - + /* writev.c */ -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c index e38e6c5f143a..f3b86da833ba 100644 --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.41 2005/07/22 10:32:08 dedekind Exp $ + * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $ * */ @@ -43,7 +43,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } if (readlen != sizeof(*ri)) { jffs2_free_raw_inode(ri); - printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", + printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", ref_offset(fd->raw), sizeof(*ri), readlen); return -EIO; } @@ -61,7 +61,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ - if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && + if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && je32_to_cpu(ri->csize)) { ri->dsize = ri->csize; ri->csize = cpu_to_je32(0); @@ -74,7 +74,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, goto out_ri; }); - + if (ri->compr == JFFS2_COMPR_ZERO) { memset(buf, 0, len); goto out_ri; @@ -82,8 +82,8 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* Cases: Reading whole node and it's uncompressed - read directly to buffer provided, check CRC. - Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided - Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy + Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided + Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy */ if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { @@ -129,7 +129,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); if (ri->compr != JFFS2_COMPR_NONE) { D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", - je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); + je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); if (ret) { printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); @@ -191,7 +191,7 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } else { uint32_t readlen; uint32_t fragofs; /* offset within the frag to start reading */ - + fragofs = offset - frag->ofs; readlen = min(frag->size - fragofs, end - offset); D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 08f8c5ec6118..5f0652df5d47 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.142 2005/09/20 14:27:34 dedekind Exp $ + * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $ * */ @@ -116,19 +116,19 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r uint32_t *latest_mctime, uint32_t *mctime_ver) { struct jffs2_full_dirent *fd; - + /* The direntry nodes are checked during the flash scanning */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); - + /* Sanity check */ if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); return 1; } - + fd = jffs2_alloc_full_dirent(rd->nsize + 1); if (unlikely(!fd)) return -ENOMEM; @@ -144,39 +144,39 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r *latest_mctime = je32_to_cpu(rd->mctime); } - /* + /* * Copy as much of the name as possible from the raw * dirent we've already read from the flash. */ if (read > sizeof(*rd)) memcpy(&fd->name[0], &rd->name[0], min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); - + /* Do we need to copy any more of the name directly from the flash? */ if (rd->nsize + sizeof(*rd) > read) { /* FIXME: point() */ int err; int already = read - sizeof(*rd); - - err = jffs2_flash_read(c, (ref_offset(ref)) + read, + + err = jffs2_flash_read(c, (ref_offset(ref)) + read, rd->nsize - already, &read, &fd->name[already]); if (unlikely(read != rd->nsize - already) && likely(!err)) return -EIO; - + if (unlikely(err)) { JFFS2_ERROR("read remainder of name: error %d\n", err); jffs2_free_full_dirent(fd); return -EIO; } } - + fd->nhash = full_name_hash(fd->name, rd->nsize); fd->next = NULL; fd->name[rd->nsize] = '\0'; - + /* * Wheee. We now have a complete jffs2_full_dirent structure, with - * the name in it and everything. Link it into the list + * the name in it and everything. Link it into the list */ jffs2_add_fd_to_list(c, fd, fdp); @@ -198,7 +198,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref struct jffs2_tmp_dnode_info *tn; uint32_t len, csize; int ret = 1; - + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); @@ -210,7 +210,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref tn->partial_crc = 0; csize = je32_to_cpu(rd->csize); - + /* If we've never checked the CRCs on this node, check them now */ if (ref_flags(ref) == REF_UNCHECKED) { uint32_t crc; @@ -221,7 +221,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ref_offset(ref), je32_to_cpu(rd->node_crc), crc); goto free_out; } - + /* Sanity checks */ if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { @@ -313,13 +313,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ret = -ENOMEM; goto free_out; } - + tn->version = je32_to_cpu(rd->version); tn->fn->ofs = je32_to_cpu(rd->offset); tn->data_crc = je32_to_cpu(rd->data_crc); tn->csize = csize; tn->fn->raw = ref; - + /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize) @@ -329,7 +329,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); - + jffs2_add_tn_to_tree(tn, tnp); return 0; @@ -351,7 +351,7 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re { /* We don't mark unknown nodes as REF_UNCHECKED */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); - + un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { @@ -423,7 +423,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, bufstart = buf + *rdlen; len = right_size - *rdlen; } - + dbg_readinode("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); @@ -432,7 +432,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, "error code: %d.\n", len, offs, err); return err; } - + if (retlen < len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", offs, retlen, len); @@ -460,7 +460,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf int len, err; *mctime_ver = 0; - + dbg_readinode("ino #%u\n", f->inocache->ino); if (jffs2_is_writebuffered(c)) { @@ -487,7 +487,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf buf = kmalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM; - + spin_lock(&c->erase_completion_lock); valid_ref = jffs2_first_valid_node(f->inocache->nodes); if (!valid_ref && f->inocache->ino != 1) @@ -514,7 +514,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf * size = JFFS2_MIN_NODE_HEADER. */ if (jffs2_is_writebuffered(c)) { - /* + /* * We treat 'buf' as 2 adjacent wbufs. We want to * adjust bufstart such as it points to the * beginning of the node within this wbuf. @@ -540,17 +540,17 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); goto free_out; } - + if (retlen < len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); err = -EIO; goto free_out; } - + node = (union jffs2_node_union *)bufstart; - + switch (je16_to_cpu(node->u.nodetype)) { - + case JFFS2_NODETYPE_DIRENT: if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { @@ -558,21 +558,21 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (unlikely(err)) goto free_out; } - + err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; } else if (unlikely(err)) goto free_out; - + if (je32_to_cpu(node->d.version) > *highest_version) *highest_version = je32_to_cpu(node->d.version); break; case JFFS2_NODETYPE_INODE: - + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); if (unlikely(err)) @@ -588,7 +588,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (je32_to_cpu(node->i.version) > *highest_version) *highest_version = je32_to_cpu(node->i.version); - + break; default: @@ -597,7 +597,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (unlikely(err)) goto free_out; } - + err = read_unknown(c, ref, &node->u); if (err == 1) { jffs2_mark_node_obsolete(c, ref); @@ -625,7 +625,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf return err; } -static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, +static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *latest_node) { @@ -677,7 +677,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, ret = 0; /* Prevent freeing the metadata update node */ } else jffs2_mark_node_obsolete(c, fn->raw); - + BUG_ON(rb->rb_left); if (rb->rb_parent && rb->rb_parent->rb_left == rb) { /* We were then left-hand child of our parent. We need @@ -763,7 +763,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } break; - + case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); @@ -788,10 +788,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_do_clear_inode(c, f); return -ENOMEM; } - + ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); - + if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; @@ -805,7 +805,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, f->target[je32_to_cpu(latest_node->csize)] = '\0'; dbg_readinode("symlink's target '%s' cached\n", f->target); } - + /* fall through... */ case S_IFBLK: @@ -848,7 +848,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } /* Scan the list of all nodes present for this ino, build map of versions, etc. */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { dbg_readinode("read inode #%u\n", ino); @@ -864,7 +864,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, case INO_STATE_CHECKEDABSENT: f->inocache->state = INO_STATE_READING; break; - + case INO_STATE_CHECKING: case INO_STATE_GC: /* If it's in either of these states, we need @@ -957,7 +957,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) kfree(f->target); f->target = NULL; } - + fds = f->dents; while(fds) { fd = fds; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 805a166469d2..0e7456ec99fd 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -38,11 +38,11 @@ static uint32_t pseudo_random; static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s); -/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. +/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s); static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s); @@ -131,8 +131,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) /* Now decide which list to put it on */ switch(ret) { case BLK_STATE_ALLFF: - /* - * Empty block. Since we can't be sure it + /* + * Empty block. Since we can't be sure it * was entirely erased, we just queue it for erase * again. It will be marked as such when the erase * is complete. Meanwhile we still count it as empty @@ -234,7 +234,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #ifdef CONFIG_JFFS2_FS_WRITEBUFFER if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { - /* If we're going to start writing into a block which already + /* If we're going to start writing into a block which already contains data, and the end of the data isn't page-aligned, skip a little and align it. */ @@ -250,7 +250,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #endif if (c->nr_erasing_blocks) { - if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { + if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks); ret = -EIO; @@ -263,7 +263,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (buf_size) kfree(flashbuf); #ifndef __ECOS - else + else c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); #endif return ret; @@ -391,7 +391,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo if (err) return err; } - + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ ofs = 0; @@ -431,7 +431,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); -scan_more: +scan_more: while(ofs < jeb->offset + c->sector_size) { jffs2_dbg_acct_paranoia_check_nolock(c, jeb); @@ -496,7 +496,7 @@ scan_more: /* If we're only checking the beginning of a block with a cleanmarker, bail now */ - if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && + if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) { D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); return BLK_STATE_CLEANMARKER; @@ -505,7 +505,7 @@ scan_more: /* See how much more there is to read in this eraseblock... */ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); if (!buf_len) { - /* No more to read. Break out of main loop without marking + /* No more to read. Break out of main loop without marking this range of empty space as dirty (because it's not) */ D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space\n", empty_start)); @@ -540,8 +540,8 @@ scan_more: } if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { /* OK. We're out of possibilities. Whinge and move on */ - noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", - JFFS2_MAGIC_BITMASK, ofs, + noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", + JFFS2_MAGIC_BITMASK, ofs, je16_to_cpu(node->magic)); DIRTY_SPACE(4); ofs += 4; @@ -556,7 +556,7 @@ scan_more: if (hdr_crc != je32_to_cpu(node->hdr_crc)) { noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", ofs, je16_to_cpu(node->magic), - je16_to_cpu(node->nodetype), + je16_to_cpu(node->nodetype), je32_to_cpu(node->totlen), je32_to_cpu(node->hdr_crc), hdr_crc); @@ -565,7 +565,7 @@ scan_more: continue; } - if (ofs + je32_to_cpu(node->totlen) > + if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) { /* Eep. Node goes over the end of the erase block. */ printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", @@ -600,7 +600,7 @@ scan_more: if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; - + case JFFS2_NODETYPE_DIRENT: if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); @@ -620,7 +620,7 @@ scan_more: case JFFS2_NODETYPE_CLEANMARKER: D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", + printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); ofs += PAD(sizeof(struct jffs2_unknown_node)); @@ -639,7 +639,7 @@ scan_more: marker_ref->flash_offset = ofs | REF_NORMAL; marker_ref->__totlen = c->cleanmarker_size; jeb->first_node = jeb->last_node = marker_ref; - + USED_SPACE(PAD(c->cleanmarker_size)); ofs += PAD(c->cleanmarker_size); } @@ -690,7 +690,7 @@ scan_more: } } - D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, + D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); /* mark_node_obsolete can add to wasted !! */ @@ -730,7 +730,7 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin return ic; } -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; @@ -740,11 +740,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); /* We do very little here now. Just check the ino# to which we should attribute - this node; we can do all the CRC checking etc. later. There's a tradeoff here -- + this node; we can do all the CRC checking etc. later. There's a tradeoff here -- we used to scan the flash once only, reading everything we want from it into memory, then building all our in-core data structures and freeing the extra information. Now we allow the first part of the mount to complete a lot quicker, - but we have to go _back_ to the flash in order to finish the CRC checking, etc. + but we have to go _back_ to the flash in order to finish the CRC checking, etc. Which means that the _full_ amount of time to get to proper write mode with GC operational may actually be _longer_ than before. Sucks to be me. */ @@ -790,7 +790,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc jeb->last_node->next_phys = raw; jeb->last_node = raw; - D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", + D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", je32_to_cpu(ri->ino), je32_to_cpu(ri->version), je32_to_cpu(ri->offset), je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); @@ -806,7 +806,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; @@ -840,7 +840,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo crc = crc32(0, fd->name, rd->nsize); if (crc != je32_to_cpu(rd->name_crc)) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(rd->name_crc), crc); + ofs, je32_to_cpu(rd->name_crc), crc); D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); jffs2_free_full_dirent(fd); /* FIXME: Why do we believe totlen? */ @@ -860,7 +860,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo jffs2_free_raw_node_ref(raw); return -ENOMEM; } - + raw->__totlen = PAD(je32_to_cpu(rd->totlen)); raw->flash_offset = ofs | REF_PRISTINE; raw->next_phys = NULL; diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 308251266c6c..fb9cec61fcf2 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -82,7 +82,7 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) je32_to_cpu(item->d.ino)); break; default: - JFFS2_WARNING("UNKNOWN node type %u\n", + JFFS2_WARNING("UNKNOWN node type %u\n", je16_to_cpu(item->u.nodetype)); return 1; } @@ -174,7 +174,7 @@ void jffs2_sum_disable_collecting(struct jffs2_summary *s) s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; } -int jffs2_sum_is_disabled(struct jffs2_summary *s) +int jffs2_sum_is_disabled(struct jffs2_summary *s) { return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE); } @@ -609,7 +609,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; sdrnt_ptr->type = c->summary->sum_list_head->d.type; - memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, + memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, c->summary->sum_list_head->d.nsize); wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); @@ -687,7 +687,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); infosize = sizeof(struct jffs2_raw_summary) + datasize; padsize = jeb->free_size - infosize; - infosize += padsize; + infosize += padsize; datasize += padsize; /* Is there enough space for summary? */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 99028af3f69e..9e0b5458d9c0 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.109 2005/09/07 08:34:55 havasi Exp $ + * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -62,7 +62,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); - up(&c->alloc_sem); + up(&c->alloc_sem); return 0; } @@ -112,7 +112,7 @@ static int jffs2_sb_set(struct super_block *sb, void *data) } static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, - int flags, const char *dev_name, + int flags, const char *dev_name, void *data, struct mtd_info *mtd) { struct super_block *sb; @@ -172,7 +172,7 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, } static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, - int flags, const char *dev_name, + int flags, const char *dev_name, void *data, int mtdnr) { struct mtd_info *mtd; @@ -201,7 +201,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, /* The preferred way of mounting in future; especially when CONFIG_BLK_DEV is implemented - we specify the underlying - MTD device by number or by name, so that we don't require + MTD device by number or by name, so that we don't require block device support to be present in the kernel. */ /* FIXME: How to do the root fs this way? */ @@ -225,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, } else if (isdigit(dev_name[3])) { /* Mount by MTD device number name */ char *endptr; - + mtdnr = simple_strtoul(dev_name+3, &endptr, 0); if (!*endptr) { /* It was a valid number */ @@ -235,7 +235,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, } } - /* Try the old way - the hack where we allowed users to mount + /* Try the old way - the hack where we allowed users to mount /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); @@ -376,5 +376,5 @@ module_exit(exit_jffs2_fs); MODULE_DESCRIPTION("The Journalling Flash File System, v2"); MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for +MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for // the sake of this tag. It's Free Software. diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 6fd5ee4f90b7..d55754fe8925 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ + * $Id: symlink.c,v 1.19 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -21,7 +21,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); struct inode_operations jffs2_symlink_inode_operations = -{ +{ .readlink = generic_readlink, .follow_link = jffs2_follow_link, .setattr = jffs2_setattr @@ -44,7 +44,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) * stopped using our f->target string which we provide by means of * nd_set_link() call. */ - + if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); p = ERR_PTR(-EIO); @@ -52,7 +52,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); nd_set_link(nd, p); - + /* * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe * since the only way that may cause f->target to be changed is iput() operation. diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 44d8a894a41b..242cd53a970c 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -188,7 +188,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* Find the first node to be recovered, by skipping over every node which ends before the wbuf starts, or which is obsolete. */ first_raw = &jeb->first_node; - while (*first_raw && + while (*first_raw && (ref_obsolete(*first_raw) || (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", @@ -237,7 +237,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); else ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); - + if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { /* ECC recovered */ ret = 0; @@ -274,15 +274,15 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) if (end-start >= c->wbuf_pagesize) { /* Need to do another write immediately, but it's possible that this is just because the wbuf itself is completely - full, and there's nothing earlier read back from the - flash. Hence 'buf' isn't necessarily what we're writing + full, and there's nothing earlier read back from the + flash. Hence 'buf' isn't necessarily what we're writing from. */ unsigned char *rewrite_buf = buf?:c->wbuf; uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", towrite, ofs)); - + #ifdef BREAKMEHEADER static int breakme; if (breakme++ == 20) { @@ -434,7 +434,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) this happens, if we have a change to a new block, or if fsync forces us to flush the writebuffer. if we have a switch to next page, we will not have - enough remaining space for this. + enough remaining space for this. */ if (pad ) { c->wbuf_len = PAD(c->wbuf_len); @@ -442,7 +442,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR with 8 byte page size */ memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); - + if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -453,7 +453,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } /* else jffs2_flash_writev has actually filled in the rest of the buffer for us, and will deal with the node refs etc. later. */ - + #ifdef BREAKME static int breakme; if (breakme++ == 20) { @@ -462,9 +462,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, brokenbuf, NULL, c->oobinfo); ret = -EIO; - } else + } else #endif - + if (jffs2_cleanmarker_oob(c)) ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); else @@ -485,7 +485,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } spin_lock(&c->erase_completion_lock); - + /* Adjust free size of the block if we padded. */ if (pad) { struct jffs2_eraseblock *jeb; @@ -495,7 +495,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", (jeb==c->nextblock)?"next":"", jeb->offset)); - /* wbuf_pagesize - wbuf_len is the amount of space that's to be + /* wbuf_pagesize - wbuf_len is the amount of space that's to be padded. If there is less free space in the block than that, something screwed up */ if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { @@ -523,9 +523,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) return 0; } -/* Trigger garbage collection to flush the write-buffer. +/* Trigger garbage collection to flush the write-buffer. If ino arg is zero, do it if _any_ real (i.e. not GC) writes are - outstanding. If ino arg non-zero, do it only if a write for the + outstanding. If ino arg non-zero, do it only if a write for the given inode is outstanding. */ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) { @@ -620,13 +620,13 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig /* If not NAND flash, don't bother */ if (!jffs2_is_writebuffered(c)) return jffs2_flash_direct_writev(c, invecs, count, to, retlen); - + down_write(&c->wbuf_sem); /* If wbuf_ofs is not initialized, set it to target address */ if (c->wbuf_ofs == 0xFFFFFFFF) { c->wbuf_ofs = PAGE_DIV(to); - c->wbuf_len = PAGE_MOD(to); + c->wbuf_len = PAGE_MOD(to); memset(c->wbuf,0xff,c->wbuf_pagesize); } @@ -640,10 +640,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig memset(c->wbuf,0xff,c->wbuf_pagesize); } } - - /* Sanity checks on target address. - It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), - and it's permitted to write at the beginning of a new + + /* Sanity checks on target address. + It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), + and it's permitted to write at the beginning of a new erase block. Anything else, and you die. New block starts at xxx000c (0-b = block header) */ @@ -661,8 +661,8 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig } /* set pointer to new block */ c->wbuf_ofs = PAGE_DIV(to); - c->wbuf_len = PAGE_MOD(to); - } + c->wbuf_len = PAGE_MOD(to); + } if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { /* We're not writing immediately after the writebuffer. Bad. */ @@ -682,21 +682,21 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig invec = 0; outvec = 0; - /* Fill writebuffer first, if already in use */ + /* Fill writebuffer first, if already in use */ if (c->wbuf_len) { uint32_t invec_ofs = 0; - /* adjust alignment offset */ + /* adjust alignment offset */ if (c->wbuf_len != PAGE_MOD(to)) { c->wbuf_len = PAGE_MOD(to); /* take care of alignment to next page */ if (!c->wbuf_len) c->wbuf_len = c->wbuf_pagesize; } - + while(c->wbuf_len < c->wbuf_pagesize) { uint32_t thislen; - + if (invec == count) goto alldone; @@ -704,17 +704,17 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig if (thislen >= invecs[invec].iov_len) thislen = invecs[invec].iov_len; - + invec_ofs = thislen; memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); c->wbuf_len += thislen; donelen += thislen; /* Get next invec, if actual did not fill the buffer */ - if (c->wbuf_len < c->wbuf_pagesize) + if (c->wbuf_len < c->wbuf_pagesize) invec++; - } - + } + /* write buffer is full, flush buffer */ ret = __jffs2_flush_wbuf(c, NOPAD); if (ret) { @@ -773,10 +773,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig /* We did cross a page boundary, so we write some now */ if (jffs2_cleanmarker_oob(c)) - ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); + ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); else ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); - + if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { /* At this point we have no problem, c->wbuf is empty. However refile nextblock to avoid @@ -793,7 +793,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig spin_unlock(&c->erase_completion_lock); goto exit; } - + donelen += wbuf_retlen; c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); @@ -837,7 +837,7 @@ alldone: jffs2_wbuf_dirties_inode(c, ino); ret = 0; - + exit: up_write(&c->wbuf_sem); return ret; @@ -880,18 +880,18 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re if ( (ret == -EBADMSG) && (*retlen == len) ) { printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", len, ofs); - /* - * We have the raw data without ECC correction in the buffer, maybe + /* + * We have the raw data without ECC correction in the buffer, maybe * we are lucky and all data or parts are correct. We check the node. * If data are corrupted node check will sort it out. * We keep this block, it will fail on write or erase and the we * mark it bad. Or should we do that now? But we should give him a chance. - * Maybe we had a system crash or power loss before the ecc write or + * Maybe we had a system crash or power loss before the ecc write or * a erase was completed. * So we return success. :) */ ret = 0; - } + } /* if no writebuffer available or write buffer empty, return */ if (!c->wbuf_pagesize || !c->wbuf_len) @@ -906,16 +906,16 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ goto exit; lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ - if (lwbf > len) + if (lwbf > len) lwbf = len; - } else { + } else { orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ if (orbf > len) /* is write beyond write buffer ? */ goto exit; lwbf = len - orbf; /* number of bytes to copy */ - if (lwbf > c->wbuf_len) + if (lwbf > c->wbuf_len) lwbf = c->wbuf_len; - } + } if (lwbf > 0) memcpy(buf+orbf,c->wbuf+owbf,lwbf); @@ -943,7 +943,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); return -ENOMEM; } - /* + /* * if mode = 0, we scan for a total empty oob area, else we have * to take care of the cleanmarker in the first page of the block */ @@ -952,41 +952,41 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); goto out; } - + if (retlen < len) { D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); ret = -EIO; goto out; } - + /* Special check for first page */ for(i = 0; i < oob_size ; i++) { /* Yeah, we know about the cleanmarker. */ - if (mode && i >= c->fsdata_pos && + if (mode && i >= c->fsdata_pos && i < c->fsdata_pos + c->fsdata_len) continue; if (buf[i] != 0xFF) { D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", buf[i], i, jeb->offset)); - ret = 1; + ret = 1; goto out; } } - /* we know, we are aligned :) */ + /* we know, we are aligned :) */ for (page = oob_size; page < len; page += sizeof(long)) { unsigned long dat = *(unsigned long *)(&buf[page]); if(dat != -1) { - ret = 1; + ret = 1; goto out; } } out: - kfree(buf); - + kfree(buf); + return ret; } @@ -1068,7 +1068,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc n.totlen = cpu_to_je32(8); ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); - + if (ret) { D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); return ret; @@ -1080,7 +1080,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } -/* +/* * On NAND we try to mark this block bad. If the block was erased more * than MAX_ERASE_FAILURES we mark it finaly bad. * Don't care about failures. This block remains on the erase-pending @@ -1101,7 +1101,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset)); ret = c->mtd->block_markbad(c->mtd, bad_offset); - + if (ret) { D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); return ret; @@ -1125,7 +1125,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) /* Do this only, if we have an oob buffer */ if (!c->mtd->oobsize) return 0; - + /* Cleanmarker is out-of-band, so inline size zero */ c->cleanmarker_size = 0; @@ -1151,7 +1151,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; c->badblock_pos = 15; break; - + default: D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); return -EINVAL; @@ -1168,7 +1168,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) init_rwsem(&c->wbuf_sem); c->wbuf_pagesize = c->mtd->oobblock; c->wbuf_ofs = 0xFFFFFFFF; - + c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) return -ENOMEM; @@ -1194,13 +1194,13 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) int jffs2_dataflash_setup(struct jffs2_sb_info *c) { c->cleanmarker_size = 0; /* No cleanmarkers needed */ - + /* Initialize write buffer */ init_rwsem(&c->wbuf_sem); - - + + c->wbuf_pagesize = c->mtd->erasesize; - + /* Find a suitable c->sector_size * - Not too much sectors * - Sectors have to be at least 4 K + some bytes @@ -1210,11 +1210,11 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { */ c->sector_size = 8 * c->mtd->erasesize; - + while (c->sector_size < 8192) { c->sector_size *= 2; } - + /* It may be necessary to adjust the flash size */ c->flash_size = c->mtd->size; @@ -1222,7 +1222,7 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { c->flash_size = (c->flash_size / c->sector_size) * c->sector_size; printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size); }; - + c->wbuf_ofs = 0xFFFFFFFF; c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index ea411518d801..1342f0158e9b 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.96 2005/09/07 08:34:55 havasi Exp $ + * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -54,7 +54,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint return 0; } -/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, +/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, write it to the flash, link it into the existing inode/fragment list */ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) @@ -86,7 +86,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 raw = jffs2_alloc_raw_node_ref(); if (!raw) return ERR_PTR(-ENOMEM); - + fn = jffs2_alloc_full_dnode(); if (!fn) { jffs2_free_raw_node_ref(raw); @@ -110,7 +110,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { BUG_ON(!retried); D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, " - "highest version %d -> updating dnode\n", + "highest version %d -> updating dnode\n", je32_to_cpu(ri->version), f->highest_version)); ri->version = cpu_to_je32(++f->highest_version); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); @@ -120,7 +120,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 (alloc_mode==ALLOC_GC)?0:f->inocache->ino); if (ret || (retlen != sizeof(*ri) + datalen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", sizeof(*ri)+datalen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ @@ -128,10 +128,10 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Doesn't belong to any inode */ raw->next_in_ino = NULL; - /* Don't change raw->size to match retlen. We may have + /* Don't change raw->size to match retlen. We may have written the node header already, and only the data will seem corrupted, in which case the scan would skip over - any node we write before the original intended end of + any node we write before the original intended end of this node */ raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, raw); @@ -148,7 +148,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 retried = 1; D1(printk(KERN_DEBUG "Retrying failed write.\n")); - + jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -159,7 +159,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); @@ -181,9 +181,9 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. + /* If node covers at least a whole page, or if it starts at the + beginning of a page and runs to the end of the file, or if + it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. */ if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && @@ -201,7 +201,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 spin_unlock(&c->erase_completion_lock); D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", - flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), + flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); @@ -221,7 +221,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff int retried = 0; int ret; - D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", + D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), je32_to_cpu(rd->name_crc))); @@ -235,7 +235,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff vecs[0].iov_len = sizeof(*rd); vecs[1].iov_base = (unsigned char *)name; vecs[1].iov_len = namelen; - + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); raw = jffs2_alloc_raw_node_ref(); @@ -276,7 +276,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); if (ret || (retlen != sizeof(*rd) + namelen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", sizeof(*rd)+namelen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ if (retlen) { @@ -307,7 +307,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); @@ -346,7 +346,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff we don't have to go digging in struct inode or its equivalent. It should set: mode, uid, gid, (starting)isize, atime, ctime, mtime */ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, + struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen) { int ret = 0; @@ -354,7 +354,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", f->inocache->ino, offset, writelen)); - + while(writelen) { struct jffs2_full_dnode *fn; unsigned char *comprbuf = NULL; @@ -451,8 +451,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str uint32_t alloclen, phys_ofs; int ret; - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); @@ -477,7 +477,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str jffs2_complete_reservation(c); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -486,7 +486,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str jffs2_complete_reservation(c); ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); - + if (ret) { /* Eep. */ D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); @@ -519,9 +519,9 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_dirent(rd); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); up(&dir_f->sem); @@ -548,7 +548,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t alloclen, phys_ofs; int ret; - if (1 /* alternative branch needs testing */ || + if (1 /* alternative branch needs testing */ || !jffs2_can_mark_obsolete(c)) { /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ @@ -570,7 +570,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - + rd->pino = cpu_to_je32(dir_f->inocache->ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(0); @@ -581,7 +581,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); - + jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { @@ -600,7 +600,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, down(&dir_f->sem); while ((*prev) && (*prev)->nhash <= nhash) { - if ((*prev)->nhash == nhash && + if ((*prev)->nhash == nhash && !memcmp((*prev)->name, name, namelen) && !(*prev)->name[namelen]) { struct jffs2_full_dirent *this = *prev; @@ -621,7 +621,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, /* dead_f is NULL if this was a rename not a real unlink */ /* Also catch the !f->inocache case, where there was a dirent pointing to an inode which didn't exist. */ - if (dead_f && dead_f->inocache) { + if (dead_f && dead_f->inocache) { down(&dead_f->sem); @@ -629,9 +629,9 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, while (dead_f->dents) { /* There can be only deleted ones */ fd = dead_f->dents; - + dead_f->dents = fd->next; - + if (fd->ino) { printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", dead_f->inocache->ino, fd->name, fd->ino); @@ -672,7 +672,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint jffs2_free_raw_dirent(rd); return ret; } - + down(&dir_f->sem); /* Build a deletion node */ @@ -693,7 +693,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); - + jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 2788880368c4..cf792bb3c726 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -5,7 +5,7 @@ * * Created by David Woodhouse * - * For licensing information, see the file 'LICENCE' in the + * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ @@ -70,10 +70,10 @@ //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) -#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at - mount time, don't wait for it to +#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at + mount time, don't wait for it to happen later */ -#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific +#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific compression type */ @@ -120,7 +120,7 @@ struct jffs2_raw_dirent } __attribute__((packed)); /* The JFFS2 raw inode structure: Used for storage on physical media. */ -/* The uid, gid, atime, mtime and ctime members could be longer, but +/* The uid, gid, atime, mtime and ctime members could be longer, but are left like this for space efficiency. If and when people decide they really need them extended, it's simple enough to add support for a new type of raw node. @@ -165,7 +165,7 @@ struct jffs2_raw_summary jint32_t sum[0]; /* inode summary info */ } __attribute__((packed)); -union jffs2_node_union +union jffs2_node_union { struct jffs2_raw_inode i; struct jffs2_raw_dirent d; diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index a5db884ec607..ef85ab56302b 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I @@ -25,7 +25,7 @@ struct jffs2_inode_info { /* There may be one datanode which isn't referenced by any of the above fragments, if it contains a metadata update but no actual data - or if this is a directory inode */ - /* This also holds the _only_ dnode for symlinks/device nodes, + /* This also holds the _only_ dnode for symlinks/device nodes, etc. */ struct jffs2_full_dnode *metadata; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index fdc445b49e19..4bcfb5570221 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -20,7 +20,7 @@ struct jffs2_inodirty; /* A struct for the overall file system control. Pointers to - jffs2_sb_info structs are named `c' in the source code. + jffs2_sb_info structs are named `c' in the source code. Nee jffs_control */ struct jffs2_sb_info { @@ -35,7 +35,7 @@ struct jffs2_sb_info { struct completion gc_thread_start; /* GC thread start completion */ struct completion gc_thread_exit; /* GC thread exit completion port */ - struct semaphore alloc_sem; /* Used to protect all the following + struct semaphore alloc_sem; /* Used to protect all the following fields, and also to protect against out-of-order writing of nodes. And GC. */ uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER @@ -64,7 +64,7 @@ struct jffs2_sb_info { uint32_t nospc_dirty_size; uint32_t nr_blocks; - struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks + struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks * from the offset (blocks[ofs / sector_size]) */ struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ @@ -82,21 +82,21 @@ struct jffs2_sb_info { struct list_head bad_list; /* Bad blocks. */ struct list_head bad_used_list; /* Bad blocks with valid data in. */ - spinlock_t erase_completion_lock; /* Protect free_list and erasing_list + spinlock_t erase_completion_lock; /* Protect free_list and erasing_list against erase completion handler */ wait_queue_head_t erase_wait; /* For waiting for erases to complete */ wait_queue_head_t inocache_wq; struct jffs2_inode_cache **inocache_list; spinlock_t inocache_lock; - + /* Sem to allow jffs2_garbage_collect_deletion_dirent to - drop the erase_completion_lock while it's holding a pointer + drop the erase_completion_lock while it's holding a pointer to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ - + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER /* Write-behind buffer for NAND flash */ unsigned char *wbuf; -- cgit v1.2.3 From 03ead8427d65f6986a8bf5fd3f29a879348780ad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:37 +0000 Subject: [LIB] reed_solomon: Clean up trailing white spaces --- include/linux/rslib.h | 28 +++++++++--------- lib/reed_solomon/Makefile | 2 +- lib/reed_solomon/decode_rs.c | 36 +++++++++++------------ lib/reed_solomon/encode_rs.c | 14 ++++----- lib/reed_solomon/reed_solomon.c | 64 ++++++++++++++++++++--------------------- 5 files changed, 72 insertions(+), 72 deletions(-) (limited to 'include') diff --git a/include/linux/rslib.h b/include/linux/rslib.h index 980c8f74d8dc..ace25acfdc97 100644 --- a/include/linux/rslib.h +++ b/include/linux/rslib.h @@ -1,15 +1,15 @@ -/* +/* * include/linux/rslib.h * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * * RS code lifted from reed solomon library written by Phil Karn * Copyright 2002 Phil Karn, KA9Q * - * $Id: rslib.h,v 1.3 2004/10/05 22:08:22 gleixner Exp $ + * $Id: rslib.h,v 1.4 2005/11/07 11:14:52 gleixner 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 @@ -21,20 +21,20 @@ #include -/** +/** * struct rs_control - rs control structure - * + * * @mm: Bits per symbol * @nn: Symbols per block (= (1<mm = number of bits per symbol + * rs->mm = number of bits per symbol * rs->nn = (2^rs->mm) - 1 - * + * * Simple arithmetic modulo would return a wrong result for values * >= 3 * rs->nn */ diff --git a/lib/reed_solomon/Makefile b/lib/reed_solomon/Makefile index 747a2de29346..c3d7136827ed 100644 --- a/lib/reed_solomon/Makefile +++ b/lib/reed_solomon/Makefile @@ -1,5 +1,5 @@ # -# This is a modified version of reed solomon lib, +# This is a modified version of reed solomon lib, # obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c index d401decd6289..a58df56f09b6 100644 --- a/lib/reed_solomon/decode_rs.c +++ b/lib/reed_solomon/decode_rs.c @@ -1,22 +1,22 @@ -/* +/* * lib/reed_solomon/decode_rs.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright 2002, Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) * - * $Id: decode_rs.c,v 1.6 2004/10/22 15:41:47 gleixner Exp $ + * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $ * */ -/* Generic data width independent code which is included by the +/* Generic data width independent code which is included by the * wrappers. */ -{ +{ int deg_lambda, el, deg_omega; int i, j, r, k, pad; int nn = rs->nn; @@ -41,9 +41,9 @@ pad = nn - nroots - len; if (pad < 0 || pad >= nn) return -ERANGE; - + /* Does the caller provide the syndrome ? */ - if (s != NULL) + if (s != NULL) goto decode; /* form the syndromes; i.e., evaluate data(x) at roots of @@ -54,11 +54,11 @@ for (j = 1; j < len; j++) { for (i = 0; i < nroots; i++) { if (syn[i] == 0) { - syn[i] = (((uint16_t) data[j]) ^ + syn[i] = (((uint16_t) data[j]) ^ invmsk) & msk; } else { syn[i] = ((((uint16_t) data[j]) ^ - invmsk) & msk) ^ + invmsk) & msk) ^ alpha_to[rs_modnn(rs, index_of[syn[i]] + (fcr + i) * prim)]; } @@ -70,7 +70,7 @@ if (syn[i] == 0) { syn[i] = ((uint16_t) par[j]) & msk; } else { - syn[i] = (((uint16_t) par[j]) & msk) ^ + syn[i] = (((uint16_t) par[j]) & msk) ^ alpha_to[rs_modnn(rs, index_of[syn[i]] + (fcr+i)*prim)]; } @@ -99,14 +99,14 @@ if (no_eras > 0) { /* Init lambda to be the erasure locator polynomial */ - lambda[1] = alpha_to[rs_modnn(rs, + lambda[1] = alpha_to[rs_modnn(rs, prim * (nn - 1 - eras_pos[0]))]; for (i = 1; i < no_eras; i++) { u = rs_modnn(rs, prim * (nn - 1 - eras_pos[i])); for (j = i + 1; j > 0; j--) { tmp = index_of[lambda[j - 1]]; if (tmp != nn) { - lambda[j] ^= + lambda[j] ^= alpha_to[rs_modnn(rs, u + tmp)]; } } @@ -127,8 +127,8 @@ discr_r = 0; for (i = 0; i < r; i++) { if ((lambda[i] != 0) && (s[r - i - 1] != nn)) { - discr_r ^= - alpha_to[rs_modnn(rs, + discr_r ^= + alpha_to[rs_modnn(rs, index_of[lambda[i]] + s[r - i - 1])]; } @@ -143,7 +143,7 @@ t[0] = lambda[0]; for (i = 0; i < nroots; i++) { if (b[i] != nn) { - t[i + 1] = lambda[i + 1] ^ + t[i + 1] = lambda[i + 1] ^ alpha_to[rs_modnn(rs, discr_r + b[i])]; } else @@ -229,7 +229,7 @@ num1 = 0; for (i = deg_omega; i >= 0; i--) { if (omega[i] != nn) - num1 ^= alpha_to[rs_modnn(rs, omega[i] + + num1 ^= alpha_to[rs_modnn(rs, omega[i] + i * root[j])]; } num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)]; @@ -239,13 +239,13 @@ * lambda_pr of lambda[i] */ for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) { if (lambda[i + 1] != nn) { - den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + + den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + i * root[j])]; } } /* Apply error to data */ if (num1 != 0 && loc[j] >= pad) { - uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + + uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + index_of[num2] + nn - index_of[den])]; /* Store the error correction pattern, if a diff --git a/lib/reed_solomon/encode_rs.c b/lib/reed_solomon/encode_rs.c index 237bf65ae886..0b5b1a6728ec 100644 --- a/lib/reed_solomon/encode_rs.c +++ b/lib/reed_solomon/encode_rs.c @@ -1,19 +1,19 @@ -/* +/* * lib/reed_solomon/encode_rs.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright 2002, Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) * - * $Id: encode_rs.c,v 1.4 2004/10/22 15:41:47 gleixner Exp $ + * $Id: encode_rs.c,v 1.5 2005/11/07 11:14:59 gleixner Exp $ * */ -/* Generic data width independent code which is included by the +/* Generic data width independent code which is included by the * wrappers. * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par) */ @@ -35,16 +35,16 @@ for (i = 0; i < len; i++) { fb = index_of[((((uint16_t) data[i])^invmsk) & msk) ^ par[0]]; /* feedback term is non-zero */ - if (fb != nn) { + if (fb != nn) { for (j = 1; j < nroots; j++) { - par[j] ^= alpha_to[rs_modnn(rs, fb + + par[j] ^= alpha_to[rs_modnn(rs, fb + genpoly[nroots - j])]; } } /* Shift */ memmove(&par[0], &par[1], sizeof(uint16_t) * (nroots - 1)); if (fb != nn) { - par[nroots - 1] = alpha_to[rs_modnn(rs, + par[nroots - 1] = alpha_to[rs_modnn(rs, fb + genpoly[0])]; } else { par[nroots - 1] = 0; diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index 6604e3b1940c..f5fef948a415 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c @@ -1,22 +1,22 @@ -/* +/* * lib/reed_solomon/rslib.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * * Reed Solomon code lifted from reed solomon library written by Phil Karn * Copyright 2002 Phil Karn, KA9Q * - * $Id: rslib.c,v 1.5 2004/10/22 15:41:47 gleixner Exp $ + * $Id: rslib.c,v 1.7 2005/11/07 11:14:59 gleixner 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. * * Description: - * + * * The generic Reed Solomon library provides runtime configurable * encoding / decoding of RS codes. * Each user must call init_rs to get a pointer to a rs_control @@ -25,11 +25,11 @@ * If a structure is generated then the polynomial arrays for * fast encoding / decoding are built. This can take some time so * make sure not to call this function from a time critical path. - * Usually a module / driver should initialize the necessary + * Usually a module / driver should initialize the necessary * rs_control structure on module / driver init and release it * on exit. - * The encoding puts the calculated syndrome into a given syndrome - * buffer. + * The encoding puts the calculated syndrome into a given syndrome + * buffer. * The decoding is a two step process. The first step calculates * the syndrome over the received (data + syndrome) and calls the * second stage, which does the decoding / error correction itself. @@ -51,7 +51,7 @@ static LIST_HEAD (rslist); /* Protection for the list */ static DECLARE_MUTEX(rslistlock); -/** +/** * rs_init - Initialize a Reed-Solomon codec * * @symsize: symbol size, bits (1-8) @@ -63,7 +63,7 @@ static DECLARE_MUTEX(rslistlock); * Allocate a control structure and the polynom arrays for faster * en/decoding. Fill the arrays according to the given parameters */ -static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, +static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, int prim, int nroots) { struct rs_control *rs; @@ -124,15 +124,15 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, /* Multiply rs->genpoly[] by @**(root + x) */ for (j = i; j > 0; j--) { if (rs->genpoly[j] != 0) { - rs->genpoly[j] = rs->genpoly[j -1] ^ - rs->alpha_to[rs_modnn(rs, + rs->genpoly[j] = rs->genpoly[j -1] ^ + rs->alpha_to[rs_modnn(rs, rs->index_of[rs->genpoly[j]] + root)]; } else rs->genpoly[j] = rs->genpoly[j - 1]; } /* rs->genpoly[0] can never be zero */ - rs->genpoly[0] = - rs->alpha_to[rs_modnn(rs, + rs->genpoly[0] = + rs->alpha_to[rs_modnn(rs, rs->index_of[rs->genpoly[0]] + root)]; } /* convert rs->genpoly[] to index form for quicker encoding */ @@ -153,7 +153,7 @@ errrs: } -/** +/** * free_rs - Free the rs control structure, if its not longer used * * @rs: the control structure which is not longer used by the @@ -173,19 +173,19 @@ void free_rs(struct rs_control *rs) up(&rslistlock); } -/** +/** * init_rs - Find a matching or allocate a new rs control structure * * @symsize: the symbol size (number of bits) * @gfpoly: the extended Galois field generator polynomial coefficients, * with the 0th coefficient in the low order bit. The polynomial * must be primitive; - * @fcr: the first consecutive root of the rs code generator polynomial + * @fcr: the first consecutive root of the rs code generator polynomial * in index form * @prim: primitive element to generate polynomial roots * @nroots: RS code generator polynomial degree (number of roots) */ -struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, +struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots) { struct list_head *tmp; @@ -198,9 +198,9 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, return NULL; if (prim <= 0 || prim >= (1<= (1< 8) + if (nroots < 0 || nroots >= (1<gfpoly) continue; if (fcr != rs->fcr) - continue; + continue; if (prim != rs->prim) - continue; + continue; if (nroots != rs->nroots) continue; /* We have a matching one already */ @@ -227,18 +227,18 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, rs->users = 1; list_add(&rs->list, &rslist); } -out: +out: up(&rslistlock); return rs; } #ifdef CONFIG_REED_SOLOMON_ENC8 -/** +/** * encode_rs8 - Calculate the parity for data values (8bit data width) * * @rs: the rs control structure * @data: data field of a given type - * @len: data length + * @len: data length * @par: parity data, must be initialized by caller (usually all 0) * @invmsk: invert data mask (will be xored on data) * @@ -246,7 +246,7 @@ out: * symbol size > 8. The calling code must take care of encoding of the * syndrome result for storage itself. */ -int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, +int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, uint16_t invmsk) { #include "encode_rs.c" @@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(encode_rs8); #endif #ifdef CONFIG_REED_SOLOMON_DEC8 -/** +/** * decode_rs8 - Decode codeword (8bit data width) * * @rs: the rs control structure @@ -273,7 +273,7 @@ EXPORT_SYMBOL_GPL(encode_rs8); * syndrome result and the received parity before calling this code. */ int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len, - uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr) { #include "decode_rs.c" @@ -287,13 +287,13 @@ EXPORT_SYMBOL_GPL(decode_rs8); * * @rs: the rs control structure * @data: data field of a given type - * @len: data length + * @len: data length * @par: parity data, must be initialized by caller (usually all 0) * @invmsk: invert data mask (will be xored on data, not on parity!) * * Each field in the data array contains up to symbol size bits of valid data. */ -int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, +int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, uint16_t invmsk) { #include "encode_rs.c" @@ -302,7 +302,7 @@ EXPORT_SYMBOL_GPL(encode_rs16); #endif #ifdef CONFIG_REED_SOLOMON_DEC16 -/** +/** * decode_rs16 - Decode codeword (16bit data width) * * @rs: the rs control structure @@ -312,13 +312,13 @@ EXPORT_SYMBOL_GPL(encode_rs16); * @s: syndrome data field (if NULL, syndrome is calculated) * @no_eras: number of erasures * @eras_pos: position of erasures, can be NULL - * @invmsk: invert data mask (will be xored on data, not on parity!) + * @invmsk: invert data mask (will be xored on data, not on parity!) * @corr: buffer to store correction bitmask on eras_pos * * Each field in the data array contains up to symbol size bits of valid data. */ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len, - uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr) { #include "decode_rs.c" -- cgit v1.2.3 From 61ecfa8777d0bc8e33dc0e5c2cca9b3247da2d37 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:31 +0000 Subject: [MTD] includes: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- include/linux/mtd/bbm.h | 2 +- include/linux/mtd/blktrans.h | 4 ++-- include/linux/mtd/cfi.h | 24 +++++++++---------- include/linux/mtd/doc2000.h | 18 +++++++------- include/linux/mtd/flashchip.h | 14 +++++------ include/linux/mtd/ftl.h | 6 ++--- include/linux/mtd/gen_probe.h | 4 ++-- include/linux/mtd/jedec.h | 20 ++++++++-------- include/linux/mtd/map.h | 14 +++++------ include/linux/mtd/mtd.h | 24 +++++++++---------- include/linux/mtd/nand.h | 54 +++++++++++++++++++++--------------------- include/linux/mtd/onenand.h | 2 +- include/linux/mtd/partitions.h | 20 ++++++++-------- include/linux/mtd/physmap.h | 12 +++++----- include/linux/mtd/pmc551.h | 12 +++++----- include/linux/mtd/xip.h | 6 ++--- 16 files changed, 118 insertions(+), 118 deletions(-) (limited to 'include') diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 92b42cb7ed2e..7a7fbe87fef0 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -29,7 +29,7 @@ * @param version version read from the bbt page during scan * @param len length of the pattern, if 0 no pattern check is performed * @param maxblocks maximum number of blocks to search for a bbt. This number of - * blocks is reserved at the end of the device + * blocks is reserved at the end of the device * where the tables are written. * @param reserved_block_code if non-0, this pattern denotes a reserved * (rather than bad) block in the stored bbt diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index 4ebc2e5a16e2..f46afec6fbf8 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -1,5 +1,5 @@ /* - * $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $ + * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $ * * (C) 2003 David Woodhouse * @@ -67,6 +67,6 @@ extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); - + #endif /* __MTD_TRANS_H__ */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 360cf626c288..39f1430bd6d5 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ -/* Common Flash Interface structures +/* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $ + * $Id: cfi.h,v 1.56 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __MTD_CFI_H__ @@ -82,8 +82,8 @@ static inline int cfi_interleave_supported(int i) } -/* NB: these values must represents the number of bytes needed to meet the - * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. +/* NB: these values must represents the number of bytes needed to meet the + * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. * These numbers are used in calculations. */ #define CFI_DEVICETYPE_X8 (8 / 8) @@ -259,7 +259,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int /* * Transforms the CFI command for the given geometry (bus width & interleave). * It looks too long to be inline, but in the common case it should almost all - * get optimised away. + * get optimised away. */ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi) { @@ -268,7 +268,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf unsigned long onecmd; int i; - /* We do it this way to give the compiler a fighting chance + /* We do it this way to give the compiler a fighting chance of optimising away all the crap for 'bankwidth' larger than an unsigned long, in the common case where that support is disabled */ @@ -279,7 +279,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf wordwidth = map_bankwidth(map); words_per_bus = 1; } - + chip_mode = map_bankwidth(map) / cfi_interleave(cfi); chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); @@ -298,7 +298,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf break; } - /* Now replicate it across the size of an unsigned long, or + /* Now replicate it across the size of an unsigned long, or just to the bus width as appropriate */ switch (chips_per_word) { default: BUG(); @@ -314,7 +314,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf ; } - /* And finally, for the multi-word case, replicate it + /* And finally, for the multi-word case, replicate it in all words in the structure */ for (i=0; i < words_per_bus; i++) { val.x[i] = onecmd; @@ -325,14 +325,14 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf #define CMD(x) cfi_build_cmd((x), map, cfi) -static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, +static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, struct cfi_private *cfi) { int wordwidth, words_per_bus, chip_mode, chips_per_word; unsigned long onestat, res = 0; int i; - /* We do it this way to give the compiler a fighting chance + /* We do it this way to give the compiler a fighting chance of optimising away all the crap for 'bankwidth' larger than an unsigned long, in the common case where that support is disabled */ @@ -343,7 +343,7 @@ static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, wordwidth = map_bankwidth(map); words_per_bus = 1; } - + chip_mode = map_bankwidth(map) / cfi_interleave(cfi); chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 953e64fb8ac5..386a52cf8b1b 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -1,12 +1,12 @@ -/* +/* * Linux driver for Disk-On-Chip devices * - * Copyright (C) 1999 Machine Vision Holdings, Inc. + * Copyright (C) 1999 Machine Vision Holdings, Inc. * Copyright (C) 2001-2003 David Woodhouse * Copyright (C) 2002-2003 Greg Ungerer * Copyright (C) 2002-2003 SnapGear Inc * - * $Id: doc2000.h,v 1.24 2005/01/05 12:40:38 dwmw2 Exp $ + * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $ * * Released under GPL */ @@ -75,10 +75,10 @@ #define DoC_Mplus_CtrlConfirm 0x1076 #define DoC_Mplus_Power 0x1fff -/* How to access the device? - * On ARM, it'll be mmap'd directly with 32-bit wide accesses. +/* How to access the device? + * On ARM, it'll be mmap'd directly with 32-bit wide accesses. * On PPC, it's mmap'd and 16-bit wide. - * Others use readb/writeb + * Others use readb/writeb */ #if defined(__arm__) #define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) @@ -172,7 +172,7 @@ struct DiskOnChip { unsigned long totlen; unsigned char ChipID; /* Type of DiskOnChip */ int ioreg; - + unsigned long mfr; /* Flash IDs - only one type of flash per device */ unsigned long id; int chipshift; @@ -180,10 +180,10 @@ struct DiskOnChip { char pageadrlen; char interleave; /* Internal interleaving - Millennium Plus style */ unsigned long erasesize; - + int curfloor; int curchip; - + int numchips; struct Nand *chips; struct mtd_info *nextdoc; diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index 675776fa3e27..a293a3b78e05 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h @@ -1,12 +1,12 @@ -/* +/* * struct flchip definition - * - * Contains information about the location and state of a given flash device + * + * Contains information about the location and state of a given flash device * * (C) 2000 Red Hat. GPLd. * - * $Id: flashchip.h,v 1.17 2005/03/14 18:27:15 bjd Exp $ + * $Id: flashchip.h,v 1.18 2005/11/07 11:14:54 gleixner Exp $ * */ @@ -15,11 +15,11 @@ /* For spinlocks. sched.h includes spinlock.h from whichever directory it * happens to be in - so we don't have to care whether we're on 2.2, which - * has asm/spinlock.h, or 2.4, which has linux/spinlock.h + * has asm/spinlock.h, or 2.4, which has linux/spinlock.h */ #include -typedef enum { +typedef enum { FL_READY, FL_STATUS, FL_CFI_QUERY, @@ -45,7 +45,7 @@ typedef enum { -/* NOTE: confusingly, this can be used to refer to more than one chip at a time, +/* NOTE: confusingly, this can be used to refer to more than one chip at a time, if they're interleaved. This can even refer to individual partitions on the same physical chip when present. */ diff --git a/include/linux/mtd/ftl.h b/include/linux/mtd/ftl.h index 3678459b4535..d99609113307 100644 --- a/include/linux/mtd/ftl.h +++ b/include/linux/mtd/ftl.h @@ -1,6 +1,6 @@ /* - * $Id: ftl.h,v 1.6 2003/01/24 13:20:04 dwmw2 Exp $ - * + * $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $ + * * Derived from (and probably identical to): * ftl.h 1.7 1999/10/25 20:23:17 * @@ -12,7 +12,7 @@ * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and - * limitations under the License. + * limitations under the License. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds diff --git a/include/linux/mtd/gen_probe.h b/include/linux/mtd/gen_probe.h index 3d7bdec14f97..256e7342ed1e 100644 --- a/include/linux/mtd/gen_probe.h +++ b/include/linux/mtd/gen_probe.h @@ -1,14 +1,14 @@ /* * (C) 2001, 2001 Red Hat, Inc. * GPL'd - * $Id: gen_probe.h,v 1.3 2004/10/20 22:10:33 dwmw2 Exp $ + * $Id: gen_probe.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_GEN_PROBE_H__ #define __LINUX_MTD_GEN_PROBE_H__ #include -#include +#include #include #include diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h index 2ba0f700ddbc..9006feb218b9 100644 --- a/include/linux/mtd/jedec.h +++ b/include/linux/mtd/jedec.h @@ -1,13 +1,13 @@ /* JEDEC Flash Interface. - * This is an older type of interface for self programming flash. It is + * This is an older type of interface for self programming flash. It is * commonly use in older AMD chips and is obsolete compared with CFI. * It is called JEDEC because the JEDEC association distributes the ID codes * for the chips. * * See the AMD flash databook for information on how to operate the interface. * - * $Id: jedec.h,v 1.3 2003/05/21 11:51:01 dwmw2 Exp $ + * $Id: jedec.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_JEDEC_H__ @@ -33,16 +33,16 @@ struct jedec_flash_chip __u16 jedec; unsigned long size; unsigned long sectorsize; - + // *(__u8*)(base + (adder << addrshift)) = data << datashift // Address size = size << addrshift unsigned long base; // Byte 0 of the flash, will be unaligned unsigned int datashift; // Useful for 32bit/16bit accesses unsigned int addrshift; unsigned long offset; // linerized start. base==offset for unbanked, uninterleaved flash - + __u32 capabilities; - + // These markers are filled in by the flash_chip_scan function unsigned long start; unsigned long length; @@ -51,16 +51,16 @@ struct jedec_flash_chip struct jedec_private { unsigned long size; // Total size of all the devices - + /* Bank handling. If sum(bank_fill) == size then this is linear flash. Otherwise the mapping has holes in it. bank_fill may be used to - find the holes, but in the common symetric case - bank_fill[0] == bank_fill[*], thus addresses may be computed + find the holes, but in the common symetric case + bank_fill[0] == bank_fill[*], thus addresses may be computed mathmatically. bank_fill must be powers of two */ unsigned is_banked; unsigned long bank_fill[MAX_JEDEC_CHIPS]; - - struct jedec_flash_chip chips[MAX_JEDEC_CHIPS]; + + struct jedec_flash_chip chips[MAX_JEDEC_CHIPS]; }; #endif diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index fc28841f3409..fedfbc8a287f 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -1,6 +1,6 @@ /* Overhauled routines for dealing with different mmap regions of flash */ -/* $Id: map.h,v 1.52 2005/05/25 10:29:41 gleixner Exp $ */ +/* $Id: map.h,v 1.54 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_MAP_H__ #define __LINUX_MTD_MAP_H__ @@ -170,14 +170,14 @@ typedef union { to a chip probe routine -- either JEDEC or CFI probe or both -- via do_map_probe(). If a chip is recognised, the probe code will invoke the appropriate chip driver (if present) and return a struct mtd_info. - At which point, you fill in the mtd->module with your own module + At which point, you fill in the mtd->module with your own module address, and register it with the MTD core code. Or you could partition it and register the partitions instead, or keep it for your own private use; whatever. - + The mtd->priv field will point to the struct map_info, and any further - private data required by the chip driver is linked from the - mtd->priv->fldrv_priv field. This allows the map driver to get at + private data required by the chip driver is linked from the + mtd->priv->fldrv_priv field. This allows the map driver to get at the destructor function map->fldrv_destroy() when it's tired of living. */ @@ -214,7 +214,7 @@ struct map_info { If there is no cache to care about this can be set to NULL. */ void (*inval_cache)(struct map_info *, unsigned long, ssize_t); - /* set_vpp() must handle being reentered -- enable, enable, disable + /* set_vpp() must handle being reentered -- enable, enable, disable must leave it enabled. */ void (*set_vpp)(struct map_info *, int); @@ -353,7 +353,7 @@ static inline map_word map_word_ff(struct map_info *map) { map_word r; int i; - + if (map_bankwidth(map) < MAP_FF_LIMIT) { int bw = 8 * map_bankwidth(map); r.x[0] = (1 << bw) - 1; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index ab5804183916..e95d0463a3e5 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ -/* - * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $ +/* + * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $ * * Copyright (C) 1999-2003 David Woodhouse et al. * @@ -90,13 +90,13 @@ struct mtd_info { // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) struct nand_oobinfo oobinfo; - u_int32_t oobavail; // Number of bytes in OOB area available for fs + u_int32_t oobavail; // Number of bytes in OOB area available for fs /* Data for variable erase regions. If numeraseregions is zero, - * it means that the whole device has erasesize as given above. + * it means that the whole device has erasesize as given above. */ int numeraseregions; - struct mtd_erase_region_info *eraseregions; + struct mtd_erase_region_info *eraseregions; /* This really shouldn't be here. It can go away in 2.5 */ u_int32_t bank_size; @@ -119,10 +119,10 @@ struct mtd_info { int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - /* - * Methods to access the protection register area, present in some + /* + * Methods to access the protection register area, present in some * flash devices. The user data is one time programmable but the - * factory data is read only. + * factory data is read only. */ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); @@ -133,14 +133,14 @@ struct mtd_info { /* kvec-based read/write methods. We need these especially for NAND flash, with its limited number of write cycles per erase. - NB: The 'count' parameter is the number of _vectors_, each of + NB: The 'count' parameter is the number of _vectors_, each of which contains an (ofs, len) tuple. */ int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen); - int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, + int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, + int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); /* Sync */ @@ -204,7 +204,7 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, #define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args) #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args) #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) -#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) +#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) #ifdef CONFIG_MTD_PARTITIONS diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2d36413b2f94..da5e67b3fc70 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -24,7 +24,7 @@ * bat later if I did something naughty. * 10-11-2000 SJH Added private NAND flash structure for driver * 10-24-2000 SJH Added prototype for 'nand_scan' function - * 10-29-2001 TG changed nand_chip structure to support + * 10-29-2001 TG changed nand_chip structure to support * hardwarespecific function for accessing control lines * 02-21-2002 TG added support for different read/write adress and * ready/busy line access function @@ -36,21 +36,21 @@ * CONFIG_MTD_NAND_ECC_JFFS2 is not set * 08-10-2002 TG extensions to nand_chip structure to support HW-ECC * - * 08-29-2002 tglx nand_chip structure: data_poi for selecting + * 08-29-2002 tglx nand_chip structure: data_poi for selecting * internal / fs-driver buffer * support for 6byte/512byte hardware ECC * read_ecc, write_ecc extended for different oob-layout * oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB, * NAND_YAFFS_OOB * 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL - * Split manufacturer and device ID structures + * Split manufacturer and device ID structures * * 02-08-2004 tglx added option field to nand structure for chip anomalities * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id * update of nand_chip structure description - * 01-17-2005 dmarlin added extended commands for AG-AND device and added option + * 01-17-2005 dmarlin added extended commands for AG-AND device and added option * for BBT_AUTO_REFRESH. - * 01-20-2005 dmarlin added optional pointer to hardware specific callback for + * 01-20-2005 dmarlin added optional pointer to hardware specific callback for * extra error status checks. */ #ifndef __LINUX_MTD_NAND_H @@ -120,8 +120,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_CMD_CACHEDPROG 0x15 /* Extended commands for AG-AND device */ -/* - * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but +/* + * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but * there is no way to distinguish that from NAND_CMD_READ0 * until the remaining sequence of commands has been completed * so add a high order bit and mask it off in the command. @@ -145,7 +145,7 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_STATUS_READY 0x40 #define NAND_STATUS_WP 0x80 -/* +/* * Constants for ECC_MODES */ @@ -191,12 +191,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_CACHEPRG 0x00000008 /* Chip has copy back function */ #define NAND_COPYBACK 0x00000010 -/* AND Chip which has 4 banks and a confusing page / block +/* AND Chip which has 4 banks and a confusing page / block * assignment. See Renesas datasheet for further information */ #define NAND_IS_AND 0x00000020 /* Chip has a array of 4 pages which can be read without * additional ready /busy waits */ -#define NAND_4PAGE_ARRAY 0x00000040 +#define NAND_4PAGE_ARRAY 0x00000040 /* Chip requires that BBT is periodically rewritten to prevent * bits from adjacent blocks from 'leaking' in altering data. * This happens with the Renesas AG-AND chips, possibly others. */ @@ -219,8 +219,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* Use a flash based bad block table. This option is passed to the * default bad block table function. */ #define NAND_USE_FLASH_BBT 0x00010000 -/* The hw ecc generator provides a syndrome instead a ecc value on read - * This can only work if we have the ecc bytes directly behind the +/* The hw ecc generator provides a syndrome instead a ecc value on read + * This can only work if we have the ecc bytes directly behind the * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */ #define NAND_HWECC_SYNDROME 0x00020000 /* This option skips the bbt scan during initialization. */ @@ -252,7 +252,7 @@ struct nand_chip; /** * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices - * @lock: protection lock + * @lock: protection lock * @active: the mtd device which holds the controller currently * @wq: wait queue to sleep on if a NAND operation is in progress * used instead of the per chip wait queue when a hw controller is available @@ -265,8 +265,8 @@ struct nand_hw_control { /** * struct nand_chip - NAND Private Flash Chip Data - * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device - * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device + * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device + * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device * @read_byte: [REPLACEABLE] read one byte from the chip * @write_byte: [REPLACEABLE] write one byte to the chip * @read_word: [REPLACEABLE] read one word from the chip @@ -289,7 +289,7 @@ struct nand_hw_control { * be provided if a hardware ECC is available * @erase_cmd: [INTERN] erase command write function, selectable due to AND support * @scan_bbt: [REPLACEABLE] function to scan bad block table - * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines + * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines * @eccsize: [INTERN] databytes used per ecc-calculation * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step * @eccsteps: [INTERN] number of ecc calculation steps per page @@ -301,7 +301,7 @@ struct nand_hw_control { * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry * @chip_shift: [INTERN] number of address bits in one chip - * @data_buf: [INTERN] internal buffer for one page + oob + * @data_buf: [INTERN] internal buffer for one page + oob * @oob_buf: [INTERN] oob buffer for one eraseblock * @oobdirty: [INTERN] indicates that oob_buf must be reinitialized * @data_poi: [INTERN] pointer to a data buffer @@ -316,22 +316,22 @@ struct nand_hw_control { * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup * @bbt_md: [REPLACEABLE] bad block table mirror descriptor - * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices * @priv: [OPTIONAL] pointer to private chip date - * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks + * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks * (determine if errors are correctable) */ - + struct nand_chip { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; - + u_char (*read_byte)(struct mtd_info *mtd); void (*write_byte)(struct mtd_info *mtd, u_char byte); u16 (*read_word)(struct mtd_info *mtd); void (*write_word)(struct mtd_info *mtd, u16 word); - + void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len); void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len); int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len); @@ -396,7 +396,7 @@ struct nand_chip { * @name: Identify the device type * @id: device ID code * @pagesize: Pagesize in bytes. Either 256 or 512 or 0 - * If the pagesize is 0, then the real pagesize + * If the pagesize is 0, then the real pagesize * and the eraseize are determined from the * extended id bytes in the chip * @erasesize: Size of an erase block in the flash device. @@ -425,7 +425,7 @@ struct nand_manufacturers { extern struct nand_flash_dev nand_flash_ids[]; extern struct nand_manufacturers nand_manuf_ids[]; -/** +/** * struct nand_bbt_descr - bad block table descriptor * @options: options for this descriptor * @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE @@ -436,14 +436,14 @@ extern struct nand_manufacturers nand_manuf_ids[]; * @version: version read from the bbt page during scan * @len: length of the pattern, if 0 no pattern check is performed * @maxblocks: maximum number of blocks to search for a bbt. This number of - * blocks is reserved at the end of the device where the tables are + * blocks is reserved at the end of the device where the tables are * written. * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than * bad) block in the stored bbt - * @pattern: pattern to identify bad block table or factory marked good / + * @pattern: pattern to identify bad block table or factory marked good / * bad blocks, can be NULL, if len = 0 * - * Descriptor for the bad block table marker and the descriptor for the + * Descriptor for the bad block table marker and the descriptor for the * pattern which identifies good and bad blocks. The assumption is made * that the pattern and the version count are always located in the oob area * of the first block. diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index d27fd12d096d..f1fd4215686a 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -77,7 +77,7 @@ struct onenand_bufferram { * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * @param state [INTERN] the current state of the OneNAND device * @param autooob [REPLACEABLE] the default (auto)placement scheme - * @param bbm [REPLACEABLE] pointer to Bad Block Management + * @param bbm [REPLACEABLE] pointer to Bad Block Management * @param priv [OPTIONAL] pointer to private chip date */ struct onenand_chip { diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 50b2edfc8f11..b03f512d51b9 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: partitions.h,v 1.16 2004/11/16 18:34:40 dwmw2 Exp $ + * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $ */ #ifndef MTD_PARTITIONS_H @@ -16,25 +16,25 @@ /* * Partition definition structure: - * + * * An array of struct partition is passed along with a MTD object to * add_mtd_partitions() to create them. * * For each partition, these fields are available: * name: string that will be used to label the partition's MTD device. - * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition + * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition * will extend to the end of the master MTD device. - * offset: absolute starting position within the master MTD device; if - * defined as MTDPART_OFS_APPEND, the partition will start where the + * offset: absolute starting position within the master MTD device; if + * defined as MTDPART_OFS_APPEND, the partition will start where the * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. - * mask_flags: contains flags that have to be masked (removed) from the + * mask_flags: contains flags that have to be masked (removed) from the * master MTD flag set for the corresponding MTD partition. - * For example, to force a read-only partition, simply adding + * For example, to force a read-only partition, simply adding * MTD_WRITEABLE to the mask_flags will do the trick. * - * Note: writeable partitions require their size and offset be + * Note: writeable partitions require their size and offset be * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). - */ + */ struct mtd_partition { char *name; /* identifier string */ @@ -66,7 +66,7 @@ struct mtd_part_parser { extern int register_mtd_parser(struct mtd_part_parser *parser); extern int deregister_mtd_parser(struct mtd_part_parser *parser); -extern int parse_mtd_partitions(struct mtd_info *master, const char **types, +extern int parse_mtd_partitions(struct mtd_info *master, const char **types, struct mtd_partition **pparts, unsigned long origin); #define put_partition_parser(p) do { module_put((p)->owner); } while(0) diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h index 05aa4970677f..c7b8bcdef013 100644 --- a/include/linux/mtd/physmap.h +++ b/include/linux/mtd/physmap.h @@ -1,8 +1,8 @@ /* - * For boards with physically mapped flash and using + * For boards with physically mapped flash and using * drivers/mtd/maps/physmap.c mapping driver. * - * $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $ + * $Id: physmap.h,v 1.4 2005/11/07 11:14:55 gleixner Exp $ * * Copyright (C) 2003 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net @@ -18,7 +18,7 @@ #include -#if defined(CONFIG_MTD_PHYSMAP) +#if defined(CONFIG_MTD_PHYSMAP) #include #include @@ -44,12 +44,12 @@ static inline void physmap_configure(unsigned long addr, unsigned long size, int #if defined(CONFIG_MTD_PARTITIONS) /* - * Machines that wish to do flash partition may want to call this function in - * their setup routine. + * Machines that wish to do flash partition may want to call this function in + * their setup routine. * * physmap_set_partitions(mypartitions, num_parts); * - * Note that one can always override this hard-coded partition with + * Note that one can always override this hard-coded partition with * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS). */ void physmap_set_partitions(struct mtd_partition *parts, int num_parts); diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h index 113e3087f68a..a7f6d20ad407 100644 --- a/include/linux/mtd/pmc551.h +++ b/include/linux/mtd/pmc551.h @@ -1,5 +1,5 @@ /* - * $Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $ + * $Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $ * * PMC551 PCI Mezzanine Ram Device * @@ -7,7 +7,7 @@ * Mark Ferrell * Copyright 1999,2000 Nortel Networks * - * License: + * License: * As part of this driver was derrived from the slram.c driver it falls * under the same license, which is GNU General Public License v2 */ @@ -17,7 +17,7 @@ #include -#define PMC551_VERSION "$Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $\n"\ +#define PMC551_VERSION "$Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $\n"\ "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n" /* @@ -30,7 +30,7 @@ struct mypriv { u32 curr_map0; u32 asize; struct mtd_info *nextpmc551; -}; +}; /* * Function Prototypes @@ -39,7 +39,7 @@ static int pmc551_erase(struct mtd_info *, struct erase_info *); static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t); static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); /* @@ -50,7 +50,7 @@ static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_cha #endif #ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC -#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 +#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 #endif diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 863fa5a1d24e..220d50bb71cd 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: xip.h,v 1.4 2005/10/17 21:03:16 nico Exp $ + * $Id: xip.h,v 1.5 2005/11/07 11:14:55 gleixner Exp $ */ #ifndef __LINUX_MTD_XIP_H__ @@ -60,9 +60,9 @@ * overflowing. * * xip_iprefetch() - * + * * Macro to fill instruction prefetch - * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); + * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); */ #include -- cgit v1.2.3 From b00e8443c3eece823052d06ae1c7cb797ab0ddf5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 7 Nov 2005 14:35:14 +0100 Subject: [ALSA] version 1.0.10rc3 --- include/sound/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/version.h b/include/sound/version.h index ee32af20dba9..d1bd3b723967 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.10rc1" -#define CONFIG_SND_DATE " (Mon Sep 12 08:13:09 2005 UTC)" +#define CONFIG_SND_VERSION "1.0.10rc3" +#define CONFIG_SND_DATE " (Mon Nov 07 13:30:21 2005 UTC)" -- cgit v1.2.3 From e4f0648fb400a05adb7c640ce8766a7011d472d3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:37 +0000 Subject: [MTD] user-abi: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- include/mtd/inftl-user.h | 4 ++-- include/mtd/mtd-abi.h | 6 +++--- include/mtd/nftl-user.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/mtd/inftl-user.h b/include/mtd/inftl-user.h index bda4f2c8f728..9b1e2526b45e 100644 --- a/include/mtd/inftl-user.h +++ b/include/mtd/inftl-user.h @@ -1,7 +1,7 @@ /* - * $Id: inftl-user.h,v 1.1 2004/05/05 15:17:00 dwmw2 Exp $ + * $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $ * - * Parts of INFTL headers shared with userspace + * Parts of INFTL headers shared with userspace * */ diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 16e74cafd0b4..b5994ea56a5a 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -1,7 +1,7 @@ /* - * $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $ + * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $ * - * Portions of MTD ABI definition which are shared by kernel and user space + * Portions of MTD ABI definition which are shared by kernel and user space */ #ifndef __MTD_ABI_H__ @@ -81,7 +81,7 @@ struct mtd_info_user { }; struct region_info_user { - uint32_t offset; /* At which this region starts, + uint32_t offset; /* At which this region starts, * from the beginning of the MTD */ uint32_t erasesize; /* For this region */ uint32_t numblocks; /* Number of blocks in this region */ diff --git a/include/mtd/nftl-user.h b/include/mtd/nftl-user.h index 924ec0459e9c..b2bca18e7311 100644 --- a/include/mtd/nftl-user.h +++ b/include/mtd/nftl-user.h @@ -1,7 +1,7 @@ /* - * $Id: nftl-user.h,v 1.1 2004/05/05 14:44:57 dwmw2 Exp $ + * $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $ * - * Parts of NFTL headers shared with userspace + * Parts of NFTL headers shared with userspace * */ -- cgit v1.2.3 From 7d24f0b8a53261709938ffabe3e00f88f6498df9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Nov 2005 00:57:52 -0800 Subject: [PATCH] ppc64: Fix bug in SLB miss handler for hugepages This patch, however, should be applied on top of the 64k-page-size patch to fix some problems with hugepage (some pre-existing, another introduced by this patch). The patch fixes a bug in the SLB miss handler for hugepages on ppc64 introduced by the dynamic hugepage patch (commit id c594adad5653491813959277fb87a2fef54c4e05) due to a misunderstanding of the srd instruction's behaviour (mea culpa). The problem arises when a 64-bit process maps some hugepages in the low 4GB of the address space (unusual). In this case, as well as the 256M segment in question being marked for hugepages, other segments at 32G intervals will be incorrectly marked for hugepages. In the process, this patch tweaks the semantics of the hugepage bitmaps to be more sensible. Previously, an address below 4G was marked for hugepages if the appropriate segment bit in the "low areas" bitmask was set *or* if the low bit in the "high areas" bitmap was set (which would mark all addresses below 1TB for hugepage). With this patch, any given address is governed by a single bitmap. Addresses below 4GB are marked for hugepage if and only if their bit is set in the "low areas" bitmap (256M granularity). Addresses between 4GB and 1TB are marked for hugepage iff the low bit in the "high areas" bitmap is set. Higher addresses are marked for hugepage iff their bit in the "high areas" bitmap is set (1TB granularity). To avoid conflicts, this patch must be applied on top of BenH's pending patch for 64k base page size [0]. As such, this patch also addresses a hugepage problem introduced by that patch. That patch allows hugepages of 1MB in size on hardware which supports it, however, that won't work when using 4k pages (4 level pagetable), because in that case hugepage PTEs are stored at the PMD level, and each PMD entry maps 2MB. This patch simply disallows hugepages in that case (we can do something cleverer to re-enable them some other day). Built, booted, and a handful of hugepage related tests passed on POWER5 LPAR (both ARCH=powerpc and ARCH=ppc64). [0] http://gate.crashing.org/~benh/ppc64-64k-pages.diff Signed-off-by: David Gibson Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/hash_utils_64.c | 6 ++++-- arch/powerpc/mm/hugetlbpage.c | 6 ++++++ arch/powerpc/mm/slb_low.S | 13 +++++++++---- include/asm-ppc64/pgtable-4k.h | 3 +++ include/asm-ppc64/pgtable-64k.h | 3 +++ 5 files changed, 25 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index b2f3dbca6952..f15dfb92dec0 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -329,12 +329,14 @@ static void __init htab_init_page_sizes(void) */ if (mmu_psize_defs[MMU_PAGE_16M].shift) mmu_huge_psize = MMU_PAGE_16M; + /* With 4k/4level pagetables, we can't (for now) cope with a + * huge page size < PMD_SIZE */ else if (mmu_psize_defs[MMU_PAGE_1M].shift) mmu_huge_psize = MMU_PAGE_1M; /* Calculate HPAGE_SHIFT and sanity check it */ - if (mmu_psize_defs[mmu_huge_psize].shift > 16 && - mmu_psize_defs[mmu_huge_psize].shift < 28) + if (mmu_psize_defs[mmu_huge_psize].shift > MIN_HUGEPTE_SHIFT && + mmu_psize_defs[mmu_huge_psize].shift < SID_SHIFT) HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift; else HPAGE_SHIFT = 0; /* No huge pages dude ! */ diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 0073a04047e4..426c269e552e 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -212,6 +212,12 @@ static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area) BUG_ON(area >= NUM_HIGH_AREAS); + /* Hack, so that each addresses is controlled by exactly one + * of the high or low area bitmaps, the first high area starts + * at 4GB, not 0 */ + if (start == 0) + start = 0x100000000UL; + /* Check no VMAs are in the region */ vma = find_vma(mm, start); if (vma && (vma->vm_start < end)) diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index 3e18241b6f35..950ffc5848c7 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -80,12 +80,17 @@ _GLOBAL(slb_miss_kernel_load_virtual) BEGIN_FTR_SECTION b 1f END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) + cmpldi r10,16 + + lhz r9,PACALOWHTLBAREAS(r13) + mr r11,r10 + blt 5f + lhz r9,PACAHIGHHTLBAREAS(r13) srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT) - srd r9,r9,r11 - lhz r11,PACALOWHTLBAREAS(r13) - srd r11,r11,r10 - or. r9,r9,r11 + +5: srd r9,r9,r11 + andi. r9,r9,1 beq 1f _GLOBAL(slb_miss_user_load_huge) li r11,0 diff --git a/include/asm-ppc64/pgtable-4k.h b/include/asm-ppc64/pgtable-4k.h index c883a2748558..e9590c06ad92 100644 --- a/include/asm-ppc64/pgtable-4k.h +++ b/include/asm-ppc64/pgtable-4k.h @@ -23,6 +23,9 @@ #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) +/* With 4k base page size, hugepage PTEs go at the PMD level */ +#define MIN_HUGEPTE_SHIFT PMD_SHIFT + /* PUD_SHIFT determines what a third-level page table entry can map */ #define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) #define PUD_SIZE (1UL << PUD_SHIFT) diff --git a/include/asm-ppc64/pgtable-64k.h b/include/asm-ppc64/pgtable-64k.h index c5f437c86b3c..154f1840ece4 100644 --- a/include/asm-ppc64/pgtable-64k.h +++ b/include/asm-ppc64/pgtable-64k.h @@ -14,6 +14,9 @@ #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) +/* With 4k base page size, hugepage PTEs go at the PMD level */ +#define MIN_HUGEPTE_SHIFT PAGE_SHIFT + /* PMD_SHIFT determines what a second-level page table entry can map */ #define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) #define PMD_SIZE (1UL << PMD_SHIFT) -- cgit v1.2.3 From e1531b4218a7ccfc1b2234b87105201e5ebe1bbf Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:57:54 -0800 Subject: [PATCH] ia64: re-implement dma_get_cache_alignment to avoid EXPORT_SYMBOL The current ia64 implementation of dma_get_cache_alignment does not work for modules because it relies on a symbol which is not exported. Direct access to a global is a little ugly anyway, so this patch re-implements dma_get_cache_alignment in a manner similar to what is currently used for x86_64. Signed-off-by: John W. Linville Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/setup.c | 7 +++++++ include/asm-ia64/dma-mapping.h | 7 +------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index fc56ca2da358..3af6de36a482 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -92,6 +92,13 @@ extern void efi_initialize_iomem_resources(struct resource *, extern char _text[], _end[], _etext[]; unsigned long ia64_max_cacheline_size; + +int dma_get_cache_alignment(void) +{ + return ia64_max_cacheline_size; +} +EXPORT_SYMBOL(dma_get_cache_alignment); + unsigned long ia64_iobase; /* virtual address for I/O accesses */ EXPORT_SYMBOL(ia64_iobase); struct io_space io_space[MAX_IO_SPACES]; diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h index 6347c9845642..df67d40801de 100644 --- a/include/asm-ia64/dma-mapping.h +++ b/include/asm-ia64/dma-mapping.h @@ -48,12 +48,7 @@ dma_set_mask (struct device *dev, u64 mask) return 0; } -static inline int -dma_get_cache_alignment (void) -{ - extern int ia64_max_cacheline_size; - return ia64_max_cacheline_size; -} +extern int dma_get_cache_alignment(void); static inline void dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir) -- cgit v1.2.3 From 2109a2d1b175dfcffbfdac693bdbe4c4ab62f11f Mon Sep 17 00:00:00 2001 From: Pekka J Enberg Date: Mon, 7 Nov 2005 00:58:01 -0800 Subject: [PATCH] mm: rename kmem_cache_s to kmem_cache This patch renames struct kmem_cache_s to kmem_cache so we can start using it instead of kmem_cache_t typedef. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/magic-number.txt | 2 +- fs/file_table.c | 4 ++-- fs/freevxfs/vxfs_extern.h | 4 ++-- fs/xfs/linux-2.6/kmem.h | 4 ++-- include/linux/file.h | 6 +++--- include/linux/slab.h | 2 +- mm/slab.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index bd8eefa17587..af67faccf4de 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -120,7 +120,7 @@ ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_li SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c -SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c +SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c diff --git a/fs/file_table.c b/fs/file_table.c index 4dc205546547..c3a5e2fd663b 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(filp_count_lock); * context and must be fully threaded - use a local spinlock * to protect files_stat.nr_files */ -void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) +void filp_ctor(void *objp, struct kmem_cache *cachep, unsigned long cflags) { if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { @@ -46,7 +46,7 @@ void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) } } -void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) +void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags) { unsigned long flags; spin_lock_irqsave(&filp_count_lock, flags); diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index d8be917f9797..927acf70c591 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -38,7 +38,7 @@ */ -struct kmem_cache_s; +struct kmem_cache; struct super_block; struct vxfs_inode_info; struct inode; @@ -51,7 +51,7 @@ extern daddr_t vxfs_bmap1(struct inode *, long); extern int vxfs_read_fshead(struct super_block *); /* vxfs_inode.c */ -extern struct kmem_cache_s *vxfs_inode_cachep; +extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); extern struct inode * vxfs_get_fake_inode(struct super_block *, struct vxfs_inode_info *); diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 8f82c1a20dc5..c64a29cdfff3 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -30,8 +30,8 @@ #define KM_NOFS 0x0004u #define KM_MAYFAIL 0x0008u -#define kmem_zone kmem_cache_s -#define kmem_zone_t kmem_cache_t +#define kmem_zone kmem_cache +#define kmem_zone_t struct kmem_cache typedef unsigned long xfs_pflags_t; diff --git a/include/linux/file.h b/include/linux/file.h index f5bbd4c508b3..d3b1a15d5f21 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -59,9 +59,9 @@ extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag)); extern void put_filp(struct file *); extern int get_unused_fd(void); extern void FASTCALL(put_unused_fd(unsigned int fd)); -struct kmem_cache_s; -extern void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags); -extern void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags); +struct kmem_cache; +extern void filp_ctor(void * objp, struct kmem_cache *cachep, unsigned long cflags); +extern void filp_dtor(void * objp, struct kmem_cache *cachep, unsigned long dflags); extern struct file ** alloc_fd_array(int); extern void free_fd_array(struct file **, int); diff --git a/include/linux/slab.h b/include/linux/slab.h index 09b9aa60063d..d1ea4051b996 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -9,7 +9,7 @@ #if defined(__KERNEL__) -typedef struct kmem_cache_s kmem_cache_t; +typedef struct kmem_cache kmem_cache_t; #include /* kmalloc_sizes.h needs CONFIG_ options */ #include diff --git a/mm/slab.c b/mm/slab.c index 41e91794aa50..d77e5f50fba9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -368,7 +368,7 @@ static inline void kmem_list3_init(struct kmem_list3 *parent) * manages a cache. */ -struct kmem_cache_s { +struct kmem_cache { /* 1) per-cpu data, touched during every alloc/free */ struct array_cache *array[NR_CPUS]; unsigned int batchcount; -- cgit v1.2.3 From fcc188e7fdddd8b23f900e485e6b3db05e7375f4 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:11 -0800 Subject: [PATCH] ppc32: Allow ERPN for early serial to depend on CPU type The PowerPC 440SPe supports up to 16 GB of RAM, and therefore its IO registers are at 0x4_xxxx_xxxx instead of being at 0x1_xxxx_xxxx like most other PPC 440 chips. To allow for this, this patch moves the definition of the ERPN used for mapping UART0 from being hard-coded in the head_44x.S assembly code to being defined in ibm44x.h. Signed-off-by: Roland Dreier Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/head_44x.S | 4 ++-- include/asm-ppc/ibm44x.h | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 8b49679fad54..677c571aa276 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -190,8 +190,8 @@ skpinv: addi r4,r4,1 /* Increment */ /* xlat fields */ lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ -#ifndef CONFIG_440EP - ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ +#ifdef UART0_PHYS_ERPN + ori r4,r4,UART0_PHYS_ERPN /* Add ERPN if above 4GB */ #endif /* attrib fields */ diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index e5374be86aef..197a9ff23dd5 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -34,12 +34,17 @@ /* Lowest TLB slot consumed by the default pinned TLBs */ #define PPC44x_LOW_SLOT 63 -/* LS 32-bits of UART0 physical address location for early serial text debug */ +/* + * Least significant 32-bits and extended real page number (ERPN) of + * UART0 physical address location for early serial text debug + */ #if defined(CONFIG_440SP) +#define UART0_PHYS_ERPN 1 #define UART0_PHYS_IO_BASE 0xf0000200 #elif defined(CONFIG_440EP) #define UART0_PHYS_IO_BASE 0xe0000000 #else +#define UART0_PHYS_ERPN 1 #define UART0_PHYS_IO_BASE 0x40000200 #endif -- cgit v1.2.3 From 41aace4fe81e3da52fa80b8380e5d2d084f77691 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:12 -0800 Subject: [PATCH] ppc32: Dump error status for both PLB segments on 440SP The PowerPC 440SP SoC has two Processor Local Bus (PLB) segments (a high-throughput segment and a low-latency segment). Fix our PLB register definitions to cope with this, and add code to dump the status of both segments when a machine check occurs. Signed-off-by: Roland Dreier Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ibm44x_common.c | 11 +++++++++++ include/asm-ppc/ibm44x.h | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'include') diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index 5152c8e41340..ebae2e2fcea6 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -214,9 +214,20 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo /* Called from machine_check_exception */ void platform_machine_check(struct pt_regs *regs) { +#ifdef CONFIG_440SP + printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n", + mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL), + mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH), + mfdcr(DCRN_PLB0_BESRL)); + printk("PLB1: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n", + mfdcr(DCRN_PLB1_BEARH), mfdcr(DCRN_PLB1_BEARL), + mfdcr(DCRN_PLB1_ACR), mfdcr(DCRN_PLB1_BESRH), + mfdcr(DCRN_PLB1_BESRL)); +#else printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x\n", mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL), mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESR)); +#endif printk("POB0: BEAR=0x%08x%08x BESR0=0x%08x BESR1=0x%08x\n", mfdcr(DCRN_POB0_BEARH), mfdcr(DCRN_POB0_BEARL), mfdcr(DCRN_POB0_BESR0), mfdcr(DCRN_POB0_BESR1)); diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index 197a9ff23dd5..0c2ba03a1d49 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -302,6 +302,23 @@ #define MALOBISR_CH0 0x80000000 /* EOB channel 1 bit */ #define MALOBISR_CH2 0x40000000 /* EOB channel 2 bit */ +#if defined(CONFIG_440SP) +/* 440SP PLB Arbiter DCRs */ +#define DCRN_PLB_REVID 0x080 /* PLB Revision ID */ +#define DCRN_PLB_CCR 0x088 /* PLB Crossbar Control */ + +#define DCRN_PLB0_ACR 0x081 /* PLB Arbiter Control */ +#define DCRN_PLB0_BESRL 0x082 /* PLB Error Status */ +#define DCRN_PLB0_BESRH 0x083 /* PLB Error Status */ +#define DCRN_PLB0_BEARL 0x084 /* PLB Error Address Low */ +#define DCRN_PLB0_BEARH 0x085 /* PLB Error Address High */ + +#define DCRN_PLB1_ACR 0x089 /* PLB Arbiter Control */ +#define DCRN_PLB1_BESRL 0x08a /* PLB Error Status */ +#define DCRN_PLB1_BESRH 0x08b /* PLB Error Status */ +#define DCRN_PLB1_BEARL 0x08c /* PLB Error Address Low */ +#define DCRN_PLB1_BEARH 0x08d /* PLB Error Address High */ +#else /* 440GP/GX PLB Arbiter DCRs */ #define DCRN_PLB0_REVID 0x082 /* PLB Arbiter Revision ID */ #define DCRN_PLB0_ACR 0x083 /* PLB Arbiter Control */ @@ -309,6 +326,7 @@ #define DCRN_PLB0_BEARL 0x086 /* PLB Error Address Low */ #define DCRN_PLB0_BEAR DCRN_PLB0_BEARL /* 40x compatibility */ #define DCRN_PLB0_BEARH 0x087 /* PLB Error Address High */ +#endif /* 440GP/GX PLB to OPB bridge DCRs */ #define DCRN_POB0_BESR0 0x090 -- cgit v1.2.3 From b0f7b8bc57ee90138a7c429951457027a90c326f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:13 -0800 Subject: [PATCH] ppc32: Add 440SPe support Add support for the AMCC PowerPC 440SPe SoC, including PCI Express in root port mode. Signed-off-by: Roland Dreier Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/cputable.c | 10 + arch/ppc/platforms/4xx/Kconfig | 8 +- arch/ppc/platforms/4xx/Makefile | 1 + arch/ppc/platforms/4xx/ppc440spe.c | 148 +++++++++++++ arch/ppc/platforms/4xx/ppc440spe.h | 66 ++++++ arch/ppc/syslib/Makefile | 1 + arch/ppc/syslib/ibm440sp_common.c | 4 +- arch/ppc/syslib/ibm44x_common.c | 2 +- arch/ppc/syslib/ppc440spe_pcie.c | 442 +++++++++++++++++++++++++++++++++++++ arch/ppc/syslib/ppc440spe_pcie.h | 149 +++++++++++++ arch/ppc/syslib/ppc4xx_pic.c | 37 +++- include/asm-ppc/ibm44x.h | 55 +++-- 12 files changed, 904 insertions(+), 19 deletions(-) create mode 100644 arch/ppc/platforms/4xx/ppc440spe.c create mode 100644 arch/ppc/platforms/4xx/ppc440spe.h create mode 100644 arch/ppc/syslib/ppc440spe_pcie.c create mode 100644 arch/ppc/syslib/ppc440spe_pcie.h (limited to 'include') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 33c63bcf69f8..cc4e9eb1c13f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -929,6 +929,16 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, }, + { /* 440SPe Rev. A */ + .pvr_mask = 0xff000fff, + .pvr_value = 0x53000890, + .cpu_name = "440SPe Rev. A", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, #endif /* CONFIG_44x */ #ifdef CONFIG_FSL_BOOKE { /* e200z5 */ diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 76f4476cab44..108d5a730f84 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -124,9 +124,13 @@ config 440SP depends on LUAN default y +config 440SPE + bool + default n + config 440 bool - depends on 440GP || 440SP || 440EP + depends on 440GP || 440SP || 440SPE || 440EP default y config 440A @@ -168,7 +172,7 @@ config XILINX_OCP config IBM_EMAC4 bool - depends on 440GX || 440SP + depends on 440GX || 440SP || 440SPE default y config BIOS_FIXUP diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index 1dd6d7fd6a9a..694accdb59f7 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_440EP) += ibm440ep.o obj-$(CONFIG_440GP) += ibm440gp.o obj-$(CONFIG_440GX) += ibm440gx.o obj-$(CONFIG_440SP) += ibm440sp.o +obj-$(CONFIG_440SPE) += ppc440spe.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c new file mode 100644 index 000000000000..6139a0b3393e --- /dev/null +++ b/arch/ppc/platforms/4xx/ppc440spe.c @@ -0,0 +1,148 @@ +/* + * arch/ppc/platforms/4xx/ppc440spe.c + * + * PPC440SPe I/O descriptions + * + * Roland Dreier + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003, 2004 Zultys Technologies + * + * 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 + +static struct ocp_func_emac_data ppc440spe_emac0_def = { + .rgmii_idx = -1, /* No RGMII */ + .rgmii_mux = -1, /* No RGMII */ + .zmii_idx = -1, /* No ZMII */ + .zmii_mux = -1, /* No ZMII */ + .mal_idx = 0, /* MAL device index */ + .mal_rx_chan = 0, /* MAL rx channel number */ + .mal_tx_chan = 0, /* MAL tx channel number */ + .wol_irq = 61, /* WOL interrupt number */ + .mdio_idx = -1, /* No shared MDIO */ + .tah_idx = -1, /* No TAH */ +}; +OCP_SYSFS_EMAC_DATA() + +static struct ocp_func_mal_data ppc440spe_mal0_def = { + .num_tx_chans = 1, /* Number of TX channels */ + .num_rx_chans = 1, /* Number of RX channels */ + .txeob_irq = 38, /* TX End Of Buffer IRQ */ + .rxeob_irq = 39, /* RX End Of Buffer IRQ */ + .txde_irq = 34, /* TX Descriptor Error IRQ */ + .rxde_irq = 35, /* RX Descriptor Error IRQ */ + .serr_irq = 33, /* MAL System Error IRQ */ + .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */ +}; +OCP_SYSFS_MAL_DATA() + +static struct ocp_func_iic_data ppc440spe_iic0_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; + +static struct ocp_func_iic_data ppc440spe_iic1_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; +OCP_SYSFS_IIC_DATA() + +struct ocp_def core_ocp[] = { + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 0, + .paddr = PPC440SPE_UART0_ADDR, + .irq = UART0_INT, + .pm = IBM_CPM_UART0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 1, + .paddr = PPC440SPE_UART1_ADDR, + .irq = UART1_INT, + .pm = IBM_CPM_UART1, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 2, + .paddr = PPC440SPE_UART2_ADDR, + .irq = UART2_INT, + .pm = IBM_CPM_UART2, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = 0x00000004f0000400ULL, + .irq = 2, + .pm = IBM_CPM_IIC0, + .additions = &ppc440spe_iic0_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 1, + .paddr = 0x00000004f0000500ULL, + .irq = 3, + .pm = IBM_CPM_IIC1, + .additions = &ppc440spe_iic1_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_GPIO, + .index = 0, + .paddr = 0x00000004f0000700ULL, + .irq = OCP_IRQ_NA, + .pm = IBM_CPM_GPIO0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_MAL, + .paddr = OCP_PADDR_NA, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + .additions = &ppc440spe_mal0_def, + .show = &ocp_show_mal_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_EMAC, + .index = 0, + .paddr = 0x00000004f0000800ULL, + .irq = 60, + .pm = OCP_CPM_NA, + .additions = &ppc440spe_emac0_def, + .show = &ocp_show_emac_data, + }, + { .vendor = OCP_VENDOR_INVALID + } +}; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffffffff, + .triggering = 0x010f0004, + .ext_irq_mask = 0x00000000, + }, + { .polarity = 0xffffffff, + .triggering = 0x001f8040, + .ext_irq_mask = 0x00007c30, /* IRQ6 - IRQ7, IRQ8 - IRQ12 */ + }, + { .polarity = 0xffffffff, + .triggering = 0x00000000, + .ext_irq_mask = 0x000000fc, /* IRQ0 - IRQ5 */ + }, + { .polarity = 0xffffffff, + .triggering = 0x00000000, + .ext_irq_mask = 0x00000000, + }, +}; diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h new file mode 100644 index 000000000000..2216846973b8 --- /dev/null +++ b/arch/ppc/platforms/4xx/ppc440spe.h @@ -0,0 +1,66 @@ +/* + * arch/ppc/platforms/4xx/ibm440spe.h + * + * PPC440SPe definitions + * + * Roland Dreier + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * Matt Porter + * Copyright 2004-2005 MontaVista Software, Inc. + * + * 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. + */ + +#ifdef __KERNEL__ +#ifndef __PPC_PLATFORMS_PPC440SPE_H +#define __PPC_PLATFORMS_PPC440SPE_H + +#include + +#include + +/* UART */ +#define PPC440SPE_UART0_ADDR 0x00000004f0000200ULL +#define PPC440SPE_UART1_ADDR 0x00000004f0000300ULL +#define PPC440SPE_UART2_ADDR 0x00000004f0000600ULL +#define UART0_INT 0 +#define UART1_INT 1 +#define UART2_INT 37 + +/* Clock and Power Management */ +#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ +#define IBM_CPM_IIC1 0x40000000 /* IIC interface */ +#define IBM_CPM_PCI 0x20000000 /* PCI bridge */ +#define IBM_CPM_CPU 0x02000000 /* processor core */ +#define IBM_CPM_DMA 0x01000000 /* DMA controller */ +#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ +#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ +#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ +#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ +#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ +#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ +#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ +#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ +#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ +#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ +#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ +#define IBM_CPM_UART0 0x00000200 /* serial port 0 */ +#define IBM_CPM_UART1 0x00000100 /* serial port 1 */ +#define IBM_CPM_UART2 0x00000100 /* serial port 1 */ +#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ +#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ +#define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */ + +#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ + | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ + | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ + | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \ + | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \ + | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \ + | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 ) +#endif /* __PPC_PLATFORMS_PPC440SP_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 2e58c2105225..13dff1e51f15 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_440EP) += ibm440gx_common.o obj-$(CONFIG_440GP) += ibm440gp_common.o obj-$(CONFIG_440GX) += ibm440gx_common.o obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o +obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o ifeq ($(CONFIG_4xx),y) ifeq ($(CONFIG_VIRTEX_II_PRO),y) obj-$(CONFIG_40x) += xilinx_pic.o diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c index 417d4cff77a0..cdafda127d81 100644 --- a/arch/ppc/syslib/ibm440sp_common.c +++ b/arch/ppc/syslib/ibm440sp_common.c @@ -1,7 +1,7 @@ /* * arch/ppc/syslib/ibm440sp_common.c * - * PPC440SP system library + * PPC440SP/PPC440SPe system library * * Matt Porter * Copyright 2002-2005 MontaVista Software Inc. @@ -35,7 +35,7 @@ unsigned long __init ibm440sp_find_end_of_memory(void) u32 mem_size = 0; /* Read two bank sizes and sum */ - for (i=0; i<2; i++) + for (i=0; i< MQ0_NUM_BANKS; i++) switch (mfdcr(DCRN_MQ0_BS0BAS + i) & MQ0_CONFIG_SIZE_MASK) { case MQ0_CONFIG_SIZE_8M: mem_size += PPC44x_MEM_SIZE_8M; diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index ebae2e2fcea6..a5bef9d163ab 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -214,7 +214,7 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo /* Called from machine_check_exception */ void platform_machine_check(struct pt_regs *regs) { -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n", mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL), mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH), diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c new file mode 100644 index 000000000000..1509fc1ddfb6 --- /dev/null +++ b/arch/ppc/syslib/ppc440spe_pcie.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Roland Dreier + * + * 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 + +#include +#include +#include + +#include "ppc440spe_pcie.h" + +static int +pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + + if (PCI_SLOT(devfn) != 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + offset += devfn << 12; + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8(hose->cfg_data + offset); + break; + case 2: + *val = in_le16(hose->cfg_data + offset); + break; + default: + *val = in_le32(hose->cfg_data + offset); + break; + } + + if (0) printk("%s: read %x(%d) @ %x\n", __func__, *val, len, offset); + + return PCIBIOS_SUCCESSFUL; +} + +static int +pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + + if (PCI_SLOT(devfn) != 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + offset += devfn << 12; + + switch (len) { + case 1: + out_8(hose->cfg_data + offset, val); + break; + case 2: + out_le16(hose->cfg_data + offset, val); + break; + default: + out_le32(hose->cfg_data + offset, val); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pcie_pci_ops = +{ + .read = pcie_read_config, + .write = pcie_write_config +}; + +enum { + PTYPE_ENDPOINT = 0x0, + PTYPE_LEGACY_ENDPOINT = 0x1, + PTYPE_ROOT_PORT = 0x4, + + LNKW_X1 = 0x1, + LNKW_X4 = 0x4, + LNKW_X8 = 0x8 +}; + +static void check_error(void) +{ + u32 valPE0, valPE1, valPE2; + + /* SDR0_PEGPLLLCT1 reset */ + if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) { + printk(KERN_INFO "PCIE: SDR0_PEGPLLLCT1 reset error 0x%8x\n", valPE0); + } + + valPE0 = SDR_READ(PESDR0_RCSSET); + valPE1 = SDR_READ(PESDR1_RCSSET); + valPE2 = SDR_READ(PESDR2_RCSSET); + + /* SDR0_PExRCSSET rstgu */ + if ( !(valPE0 & 0x01000000) || + !(valPE1 & 0x01000000) || + !(valPE2 & 0x01000000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstgu error\n"); + } + + /* SDR0_PExRCSSET rstdl */ + if ( !(valPE0 & 0x00010000) || + !(valPE1 & 0x00010000) || + !(valPE2 & 0x00010000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstdl error\n"); + } + + /* SDR0_PExRCSSET rstpyn */ + if ( (valPE0 & 0x00001000) || + (valPE1 & 0x00001000) || + (valPE2 & 0x00001000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstpyn error\n"); + } + + /* SDR0_PExRCSSET hldplb */ + if ( (valPE0 & 0x10000000) || + (valPE1 & 0x10000000) || + (valPE2 & 0x10000000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET hldplb error\n"); + } + + /* SDR0_PExRCSSET rdy */ + if ( (valPE0 & 0x00100000) || + (valPE1 & 0x00100000) || + (valPE2 & 0x00100000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rdy error\n"); + } + + /* SDR0_PExRCSSET shutdown */ + if ( (valPE0 & 0x00000100) || + (valPE1 & 0x00000100) || + (valPE2 & 0x00000100)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET shutdown error\n"); + } +} + +/* + * Initialize PCI Express core as described in User Manual section 27.12.1 + */ +int ppc440spe_init_pcie(void) +{ + /* Set PLL clock receiver to LVPECL */ + SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28); + + check_error(); + + printk(KERN_INFO "PCIE initialization OK\n"); + + if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) + printk(KERN_INFO "PESDR_PLLCT2 resistance calibration failed (0x%08x)\n", + SDR_READ(PESDR0_PLLLCT2)); + + /* De-assert reset of PCIe PLL, wait for lock */ + SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24)); + udelay(3); + + return 0; +} + +int ppc440spe_init_pcie_rootport(int port) +{ + static int core_init; + void __iomem *utl_base; + u32 val = 0; + int i; + + if (!core_init) { + ++core_init; + i = ppc440spe_init_pcie(); + if (i) + return i; + } + + /* + * Initialize various parts of the PCI Express core for our port: + * + * - Set as a root port and enable max width + * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). + * - Set up UTL configuration. + * - Increase SERDES drive strength to levels suggested by AMCC. + * - De-assert RSTPYN, RSTDL and RSTGU. + */ + switch (port) { + case 0: + SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12); + + SDR_WRITE(PESDR0_UTLSET1, 0x21222222); + SDR_WRITE(PESDR0_UTLSET2, 0x11000000); + + SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); + + SDR_WRITE(PESDR0_RCSSET, + (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); + break; + + case 1: + SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); + + SDR_WRITE(PESDR1_UTLSET1, 0x21222222); + SDR_WRITE(PESDR1_UTLSET2, 0x11000000); + + SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); + SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); + SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); + SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); + + SDR_WRITE(PESDR1_RCSSET, + (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); + break; + + case 2: + SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); + + SDR_WRITE(PESDR2_UTLSET1, 0x21222222); + SDR_WRITE(PESDR2_UTLSET2, 0x11000000); + + SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); + SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); + SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); + SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); + + SDR_WRITE(PESDR2_RCSSET, + (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); + break; + } + + mdelay(1000); + + switch (port) { + case 0: val = SDR_READ(PESDR0_RCSSTS); break; + case 1: val = SDR_READ(PESDR1_RCSSTS); break; + case 2: val = SDR_READ(PESDR2_RCSSTS); break; + } + + if (!(val & (1 << 20))) + printk(KERN_INFO "PCIE%d: PGRST inactive\n", port); + else + printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val); + + switch (port) { + case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break; + case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break; + case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break; + } + + /* + * Map UTL registers at 0xc_1000_0n00 + */ + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800); + break; + + case 1: + mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800); + break; + + case 2: + mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800); + } + + utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100); + + /* + * Set buffer allocations and then assert VRB and TXE. + */ + out_be32(utl_base + PEUTL_OUTTR, 0x08000000); + out_be32(utl_base + PEUTL_INTR, 0x02000000); + out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000); + out_be32(utl_base + PEUTL_PBBSZ, 0x53000000); + out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000); + out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000); + out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); + out_be32(utl_base + PEUTL_PCTL, 0x80800066); + + iounmap(utl_base); + + /* + * We map PCI Express configuration access into the 512MB regions + * PCIE0: 0xc_4000_0000 + * PCIE1: 0xc_8000_0000 + * PCIE2: 0xc_c000_0000 + */ + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); + mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ + break; + + case 1: + mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); + mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ + break; + + case 2: + mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); + mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ + break; + } + + /* + * Check for VC0 active and assert RDY. + */ + switch (port) { + case 0: + if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) + printk(KERN_WARNING "PCIE0: VC0 not active\n"); + SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); + break; + case 1: + if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) + printk(KERN_WARNING "PCIE0: VC0 not active\n"); + SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); + break; + case 2: + if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) + printk(KERN_WARNING "PCIE0: VC0 not active\n"); + SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); + break; + } + +#if 0 + /* Dump all config regs */ + for (i = 0x300; i <= 0x320; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x340; i <= 0x353; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x370; i <= 0x383; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x3a0; i <= 0x3a2; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x3c0; i <= 0x3c3; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); +#endif + + mdelay(100); + + return 0; +} + +void ppc440spe_setup_pcie(struct pci_controller *hose, int port) +{ + void __iomem *mbase; + + /* + * Map 16MB, which is enough for 4 bits of bus # + */ + hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000, + 1 << 24); + hose->ops = &pcie_pci_ops; + + /* + * Set bus numbers on our root port + */ + mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096); + out_8(mbase + PCI_PRIMARY_BUS, 0); + out_8(mbase + PCI_SECONDARY_BUS, 0); + + /* + * Set up outbound translation to hose->mem_space from PLB + * addresses at an offset of 0xd_0000_0000. We set the low + * bits of the mask to 11 to turn off splitting into 8 + * subregions and to enable the outbound translation. + */ + out_le32(mbase + PECFG_POM0LAH, 0); + out_le32(mbase + PECFG_POM0LAL, hose->mem_space.start); + + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), hose->mem_space.start); + mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), + ~(hose->mem_space.end - hose->mem_space.start) | 3); + break; + case 1: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), hose->mem_space.start); + mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), + ~(hose->mem_space.end - hose->mem_space.start) | 3); + + break; + case 2: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), hose->mem_space.start); + mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), + ~(hose->mem_space.end - hose->mem_space.start) | 3); + break; + } + + /* Set up 16GB inbound memory window at 0 */ + out_le32(mbase + PCI_BASE_ADDRESS_0, 0); + out_le32(mbase + PCI_BASE_ADDRESS_1, 0); + out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc); + out_le32(mbase + PECFG_BAR0LMPA, 0); + out_le32(mbase + PECFG_PIM0LAL, 0); + out_le32(mbase + PECFG_PIM0LAH, 0); + out_le32(mbase + PECFG_PIMEN, 0x1); + + /* Enable I/O, Mem, and Busmaster cycles */ + out_le16(mbase + PCI_COMMAND, + in_le16(mbase + PCI_COMMAND) | + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + iounmap(mbase); +} diff --git a/arch/ppc/syslib/ppc440spe_pcie.h b/arch/ppc/syslib/ppc440spe_pcie.h new file mode 100644 index 000000000000..55b765ad3272 --- /dev/null +++ b/arch/ppc/syslib/ppc440spe_pcie.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Roland Dreier + * + * 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. + */ + +#ifndef __PPC_SYSLIB_PPC440SPE_PCIE_H +#define __PPC_SYSLIB_PPC440SPE_PCIE_H + +#define DCRN_SDR0_CFGADDR 0x00e +#define DCRN_SDR0_CFGDATA 0x00f + +#define DCRN_PCIE0_BASE 0x100 +#define DCRN_PCIE1_BASE 0x120 +#define DCRN_PCIE2_BASE 0x140 +#define PCIE0 DCRN_PCIE0_BASE +#define PCIE1 DCRN_PCIE1_BASE +#define PCIE2 DCRN_PCIE2_BASE + +#define DCRN_PEGPL_CFGBAH(base) (base + 0x00) +#define DCRN_PEGPL_CFGBAL(base) (base + 0x01) +#define DCRN_PEGPL_CFGMSK(base) (base + 0x02) +#define DCRN_PEGPL_MSGBAH(base) (base + 0x03) +#define DCRN_PEGPL_MSGBAL(base) (base + 0x04) +#define DCRN_PEGPL_MSGMSK(base) (base + 0x05) +#define DCRN_PEGPL_OMR1BAH(base) (base + 0x06) +#define DCRN_PEGPL_OMR1BAL(base) (base + 0x07) +#define DCRN_PEGPL_OMR1MSKH(base) (base + 0x08) +#define DCRN_PEGPL_OMR1MSKL(base) (base + 0x09) +#define DCRN_PEGPL_REGBAH(base) (base + 0x12) +#define DCRN_PEGPL_REGBAL(base) (base + 0x13) +#define DCRN_PEGPL_REGMSK(base) (base + 0x14) +#define DCRN_PEGPL_SPECIAL(base) (base + 0x15) + +/* + * System DCRs (SDRs) + */ +#define PESDR0_PLLLCT1 0x03a0 +#define PESDR0_PLLLCT2 0x03a1 +#define PESDR0_PLLLCT3 0x03a2 + +#define PESDR0_UTLSET1 0x0300 +#define PESDR0_UTLSET2 0x0301 +#define PESDR0_DLPSET 0x0302 +#define PESDR0_LOOP 0x0303 +#define PESDR0_RCSSET 0x0304 +#define PESDR0_RCSSTS 0x0305 +#define PESDR0_HSSL0SET1 0x0306 +#define PESDR0_HSSL0SET2 0x0307 +#define PESDR0_HSSL0STS 0x0308 +#define PESDR0_HSSL1SET1 0x0309 +#define PESDR0_HSSL1SET2 0x030a +#define PESDR0_HSSL1STS 0x030b +#define PESDR0_HSSL2SET1 0x030c +#define PESDR0_HSSL2SET2 0x030d +#define PESDR0_HSSL2STS 0x030e +#define PESDR0_HSSL3SET1 0x030f +#define PESDR0_HSSL3SET2 0x0310 +#define PESDR0_HSSL3STS 0x0311 +#define PESDR0_HSSL4SET1 0x0312 +#define PESDR0_HSSL4SET2 0x0313 +#define PESDR0_HSSL4STS 0x0314 +#define PESDR0_HSSL5SET1 0x0315 +#define PESDR0_HSSL5SET2 0x0316 +#define PESDR0_HSSL5STS 0x0317 +#define PESDR0_HSSL6SET1 0x0318 +#define PESDR0_HSSL6SET2 0x0319 +#define PESDR0_HSSL6STS 0x031a +#define PESDR0_HSSL7SET1 0x031b +#define PESDR0_HSSL7SET2 0x031c +#define PESDR0_HSSL7STS 0x031d +#define PESDR0_HSSCTLSET 0x031e +#define PESDR0_LANE_ABCD 0x031f +#define PESDR0_LANE_EFGH 0x0320 + +#define PESDR1_UTLSET1 0x0340 +#define PESDR1_UTLSET2 0x0341 +#define PESDR1_DLPSET 0x0342 +#define PESDR1_LOOP 0x0343 +#define PESDR1_RCSSET 0x0344 +#define PESDR1_RCSSTS 0x0345 +#define PESDR1_HSSL0SET1 0x0346 +#define PESDR1_HSSL0SET2 0x0347 +#define PESDR1_HSSL0STS 0x0348 +#define PESDR1_HSSL1SET1 0x0349 +#define PESDR1_HSSL1SET2 0x034a +#define PESDR1_HSSL1STS 0x034b +#define PESDR1_HSSL2SET1 0x034c +#define PESDR1_HSSL2SET2 0x034d +#define PESDR1_HSSL2STS 0x034e +#define PESDR1_HSSL3SET1 0x034f +#define PESDR1_HSSL3SET2 0x0350 +#define PESDR1_HSSL3STS 0x0351 +#define PESDR1_HSSCTLSET 0x0352 +#define PESDR1_LANE_ABCD 0x0353 + +#define PESDR2_UTLSET1 0x0370 +#define PESDR2_UTLSET2 0x0371 +#define PESDR2_DLPSET 0x0372 +#define PESDR2_LOOP 0x0373 +#define PESDR2_RCSSET 0x0374 +#define PESDR2_RCSSTS 0x0375 +#define PESDR2_HSSL0SET1 0x0376 +#define PESDR2_HSSL0SET2 0x0377 +#define PESDR2_HSSL0STS 0x0378 +#define PESDR2_HSSL1SET1 0x0379 +#define PESDR2_HSSL1SET2 0x037a +#define PESDR2_HSSL1STS 0x037b +#define PESDR2_HSSL2SET1 0x037c +#define PESDR2_HSSL2SET2 0x037d +#define PESDR2_HSSL2STS 0x037e +#define PESDR2_HSSL3SET1 0x037f +#define PESDR2_HSSL3SET2 0x0380 +#define PESDR2_HSSL3STS 0x0381 +#define PESDR2_HSSCTLSET 0x0382 +#define PESDR2_LANE_ABCD 0x0383 + +/* + * UTL register offsets + */ +#define PEUTL_PBBSZ 0x20 +#define PEUTL_OPDBSZ 0x68 +#define PEUTL_IPHBSZ 0x70 +#define PEUTL_IPDBSZ 0x78 +#define PEUTL_OUTTR 0x90 +#define PEUTL_INTR 0x98 +#define PEUTL_PCTL 0xa0 +#define PEUTL_RCIRQEN 0xb8 + +/* + * Config space register offsets + */ +#define PECFG_BAR0LMPA 0x210 +#define PECFG_BAR0HMPA 0x214 +#define PECFG_PIMEN 0x33c +#define PECFG_PIM0LAL 0x340 +#define PECFG_PIM0LAH 0x344 +#define PECFG_POM0LAL 0x380 +#define PECFG_POM0LAH 0x384 + +int ppc440spe_init_pcie(void); +int ppc440spe_init_pcie_rootport(int port); +void ppc440spe_setup_pcie(struct pci_controller *hose, int port); + +#endif /* __PPC_SYSLIB_PPC440SPE_PCIE_H */ diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c index 0b435633a0d1..aa4165144ec2 100644 --- a/arch/ppc/syslib/ppc4xx_pic.c +++ b/arch/ppc/syslib/ppc4xx_pic.c @@ -38,6 +38,7 @@ extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak)); #define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f))) #define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq) #define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq) +#define IRQ_MASK_UIC3(irq) IRQ_MASK_UICx(irq) #define UIC_HANDLERS(n) \ static void ppc4xx_uic##n##_enable(unsigned int irq) \ @@ -88,7 +89,38 @@ static void ppc4xx_uic##n##_end(unsigned int irq) \ .end = ppc4xx_uic##n##_end, \ } \ -#if NR_UICS == 3 +#if NR_UICS == 4 +#define ACK_UIC0_PARENT +#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); +#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC); +#define ACK_UIC3_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC); +UIC_HANDLERS(0); +UIC_HANDLERS(1); +UIC_HANDLERS(2); +UIC_HANDLERS(3); + +static int ppc4xx_pic_get_irq(struct pt_regs *regs) +{ + u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); + if (uic0 & UIC0_UIC1NC) + return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); + else if (uic0 & UIC0_UIC2NC) + return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2))); + else if (uic0 & UIC0_UIC3NC) + return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3))); + else + return uic0 ? 32 - ffs(uic0) : -1; +} + +static void __init ppc4xx_pic_impl_init(void) +{ + /* Enable cascade interrupts in UIC0 */ + ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC; + mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC); + mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); +} + +#elif NR_UICS == 3 #define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC); #define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC); #define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC); @@ -170,6 +202,9 @@ static struct ppc4xx_uic_impl { { .decl = DECLARE_UIC(1), .base = UIC1 }, #if NR_UICS > 2 { .decl = DECLARE_UIC(2), .base = UIC2 }, +#if NR_UICS > 3 + { .decl = DECLARE_UIC(3), .base = UIC3 }, +#endif #endif #endif }; diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index 0c2ba03a1d49..f835066fb3ca 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -41,6 +41,9 @@ #if defined(CONFIG_440SP) #define UART0_PHYS_ERPN 1 #define UART0_PHYS_IO_BASE 0xf0000200 +#elif defined(CONFIG_440SPE) +#define UART0_PHYS_ERPN 4 +#define UART0_PHYS_IO_BASE 0xf0000200 #elif defined(CONFIG_440EP) #define UART0_PHYS_IO_BASE 0xe0000000 #else @@ -61,6 +64,11 @@ #define PPC44x_PCICFG_PAGE 0x0000000900000000ULL #define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE #define PPC44x_PCIMEM_PAGE 0x0000000a00000000ULL +#elif defined(CONFIG_440SPE) +#define PPC44x_IO_PAGE 0x0000000400000000ULL +#define PPC44x_PCICFG_PAGE 0x0000000c00000000ULL +#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE +#define PPC44x_PCIMEM_PAGE 0x0000000d00000000ULL #elif defined(CONFIG_440EP) #define PPC44x_IO_PAGE 0x0000000000000000ULL #define PPC44x_PCICFG_PAGE 0x0000000000000000ULL @@ -76,7 +84,7 @@ /* * 36-bit trap ranges */ -#if defined(CONFIG_440SP) +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) #define PPC44x_IO_LO 0xf0000000UL #define PPC44x_IO_HI 0xf0000fffUL #define PPC44x_PCI0CFG_LO 0x0ec00000UL @@ -114,7 +122,7 @@ */ -/* CPRs (440GX and 440SP) */ +/* CPRs (440GX and 440SP/440SPe) */ #define DCRN_CPR_CONFIG_ADDR 0xc #define DCRN_CPR_CONFIG_DATA 0xd @@ -135,7 +143,7 @@ mtdcr(DCRN_CPR_CONFIG_ADDR, offset); \ mtdcr(DCRN_CPR_CONFIG_DATA, data);}) -/* SDRs (440GX and 440SP) */ +/* SDRs (440GX and 440SP/440SPe) */ #define DCRN_SDR_CONFIG_ADDR 0xe #define DCRN_SDR_CONFIG_DATA 0xf #define DCRN_SDR_PFC0 0x4100 @@ -185,7 +193,7 @@ mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \ mtdcr(DCRN_SDR_CONFIG_DATA,data);}) -/* DMA (excluding 440SP) */ +/* DMA (excluding 440SP/440SPe) */ #define DCRN_DMA0_BASE 0x100 #define DCRN_DMA1_BASE 0x108 #define DCRN_DMA2_BASE 0x110 @@ -205,12 +213,20 @@ /* UIC */ #define DCRN_UIC0_BASE 0xc0 #define DCRN_UIC1_BASE 0xd0 -#define DCRN_UIC2_BASE 0x210 -#define DCRN_UICB_BASE 0x200 #define UIC0 DCRN_UIC0_BASE #define UIC1 DCRN_UIC1_BASE + +#ifdef CONFIG_440SPE +#define DCRN_UIC2_BASE 0xe0 +#define DCRN_UIC3_BASE 0xf0 +#define UIC2 DCRN_UIC2_BASE +#define UIC3 DCRN_UIC3_BASE +#else +#define DCRN_UIC2_BASE 0x210 +#define DCRN_UICB_BASE 0x200 #define UIC2 DCRN_UIC2_BASE #define UICB DCRN_UICB_BASE +#endif #define DCRN_UIC_SR(base) (base + 0x0) #define DCRN_UIC_ER(base) (base + 0x2) @@ -223,6 +239,12 @@ #define UIC0_UIC1NC 0x00000002 +#ifdef CONFIG_440SPE +#define UIC0_UIC1NC 0x00000002 +#define UIC0_UIC2NC 0x00200000 +#define UIC0_UIC3NC 0x00008000 +#endif + #define UICB_UIC0NC 0x40000000 #define UICB_UIC1NC 0x10000000 #define UICB_UIC2NC 0x04000000 @@ -302,8 +324,8 @@ #define MALOBISR_CH0 0x80000000 /* EOB channel 1 bit */ #define MALOBISR_CH2 0x40000000 /* EOB channel 2 bit */ -#if defined(CONFIG_440SP) -/* 440SP PLB Arbiter DCRs */ +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) +/* 440SP/440SPe PLB Arbiter DCRs */ #define DCRN_PLB_REVID 0x080 /* PLB Revision ID */ #define DCRN_PLB_CCR 0x088 /* PLB Crossbar Control */ @@ -430,9 +452,13 @@ #define PPC44x_MEM_SIZE_1G 0x40000000 #define PPC44x_MEM_SIZE_2G 0x80000000 -/* 440SP memory controller DCRs */ +/* 440SP/440SPe memory controller DCRs */ #define DCRN_MQ0_BS0BAS 0x40 -#define DCRN_MQ0_BS1BAS 0x41 +#if defined(CONFIG_440SP) +#define MQ0_NUM_BANKS 2 +#elif defined(CONFIG_440SPE) +#define MQ0_NUM_BANKS 4 +#endif #define MQ0_CONFIG_SIZE_MASK 0x0000fff0 #define MQ0_CONFIG_SIZE_8M 0x0000ffc0 @@ -444,8 +470,9 @@ #define MQ0_CONFIG_SIZE_512M 0x0000f000 #define MQ0_CONFIG_SIZE_1G 0x0000e000 #define MQ0_CONFIG_SIZE_2G 0x0000c000 +#define MQ0_CONFIG_SIZE_4G 0x00008000 -/* Internal SRAM Controller 440GX/440SP */ +/* Internal SRAM Controller 440GX/440SP/440SPe */ #define DCRN_SRAM0_BASE 0x000 #define DCRN_SRAM0_SB0CR (DCRN_SRAM0_BASE + 0x020) @@ -469,7 +496,7 @@ #define DCRN_SRAM0_DPC (DCRN_SRAM0_BASE + 0x02a) #define SRAM_DPC_ENABLE 0x80000000 -/* L2 Cache Controller 440GX/440SP */ +/* L2 Cache Controller 440GX/440SP/440SPe */ #define DCRN_L2C0_CFG 0x030 #define L2C_CFG_L2M 0x80000000 #define L2C_CFG_ICU 0x40000000 @@ -633,8 +660,10 @@ #define IIC_CLOCK 50 #undef NR_UICS -#ifdef CONFIG_440GX +#if defined(CONFIG_440GX) #define NR_UICS 3 +#elif defined(CONFIG_440SPE) +#define NR_UICS 4 #else #define NR_UICS 2 #endif -- cgit v1.2.3 From 90eb2665841d7b444602736e2141a01c948f75b1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:14 -0800 Subject: [PATCH] ppc32: Add Yucca (440SPe eval board) platform Add support for AMCC PowerPC 440SPe "Yucca" eval board platform. Signed-off-by: Roland Dreier Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/simple/Makefile | 6 + arch/ppc/platforms/4xx/Kconfig | 11 +- arch/ppc/platforms/4xx/Makefile | 1 + arch/ppc/platforms/4xx/yucca.c | 395 ++++++++++++++++++++++++++++++++++++++++ arch/ppc/platforms/4xx/yucca.h | 111 +++++++++++ arch/ppc/syslib/Makefile | 1 + include/asm-ppc/ibm4xx.h | 4 + 7 files changed, 527 insertions(+), 2 deletions(-) create mode 100644 arch/ppc/platforms/4xx/yucca.c create mode 100644 arch/ppc/platforms/4xx/yucca.h (limited to 'include') diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index b7bd8f61a4ad..ff0904ee889d 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -79,6 +79,12 @@ zimageinitrd-$(CONFIG_LUAN) := zImage.initrd-TREE entrypoint-$(CONFIG_LUAN) := 0x01000000 extra.o-$(CONFIG_LUAN) := pibs.o + zimage-$(CONFIG_YUCCA) := zImage-TREE +zimageinitrd-$(CONFIG_YUCCA) := zImage.initrd-TREE + end-$(CONFIG_YUCCA) := yucca + entrypoint-$(CONFIG_YUCCA) := 0x01000000 + extra.o-$(CONFIG_YUCCA) := pibs.o + zimage-$(CONFIG_OCOTEA) := zImage-TREE zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE end-$(CONFIG_OCOTEA) := ocotea diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 108d5a730f84..e70e4c6ec787 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -82,6 +82,12 @@ config LUAN help This option enables support for the IBM PPC440SP evaluation board. +config YUCCA + bool "Yucca" + select WANT_EARLY_SERIAL + help + This option enables support for the AMCC PPC440SPe evaluation board. + config OCOTEA bool "Ocotea" select WANT_EARLY_SERIAL @@ -126,7 +132,8 @@ config 440SP config 440SPE bool - default n + depends on YUCCA + default y config 440 bool @@ -162,7 +169,7 @@ config BOOKE config IBM_OCP bool - depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y config XILINX_OCP diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index 694accdb59f7..c9bb61170954 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_EP405) += ep405.o obj-$(CONFIG_BUBINGA) += bubinga.o obj-$(CONFIG_LUAN) += luan.o +obj-$(CONFIG_YUCCA) += yucca.o obj-$(CONFIG_OCOTEA) += ocotea.o obj-$(CONFIG_REDWOOD_5) += redwood5.o obj-$(CONFIG_REDWOOD_6) += redwood6.o diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c new file mode 100644 index 000000000000..e60f4bd437ec --- /dev/null +++ b/arch/ppc/platforms/4xx/yucca.c @@ -0,0 +1,395 @@ +/* + * arch/ppc/platforms/4xx/yucca.c + * + * Yucca board specific routines + * + * Roland Dreier (based on luan.c by Matt Porter) + * + * Copyright 2004-2005 MontaVista Software Inc. + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern bd_t __res; + +static struct ibm44x_clocks clocks __initdata; + +static void __init +yucca_calibrate_decr(void) +{ + unsigned int freq; + + if (mfspr(SPRN_CCR1) & CCR1_TCS) + freq = YUCCA_TMR_CLK; + else + freq = clocks.cpu; + + ibm44x_calibrate_decr(freq); +} + +static int +yucca_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: AMCC\n"); + seq_printf(m, "machine\t\t: PPC440SPe EVB (Yucca)\n"); + + return 0; +} + +static enum { + HOSE_UNKNOWN, + HOSE_PCIX, + HOSE_PCIE0, + HOSE_PCIE1, + HOSE_PCIE2 +} hose_type[4]; + +static inline int +yucca_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + + if (hose_type[hose->index] == HOSE_PCIX) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 81, -1, -1, -1 }, /* IDSEL 1 - PCIX0 Slot 0 */ + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else if (hose_type[hose->index] == HOSE_PCIE0) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 96, 97, 98, 99 }, + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else if (hose_type[hose->index] == HOSE_PCIE1) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 100, 101, 102, 103 }, + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else if (hose_type[hose->index] == HOSE_PCIE2) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 104, 105, 106, 107 }, + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } + return -1; +} + +static void __init yucca_set_emacdata(void) +{ + struct ocp_def *def; + struct ocp_func_emac_data *emacdata; + + /* Set phy_map, phy_mode, and mac_addr for the EMAC */ + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); + emacdata = def->additions; + emacdata->phy_map = 0x00000001; /* Skip 0x00 */ + emacdata->phy_mode = PHY_MODE_GMII; + memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); +} + +static int __init yucca_pcie_card_present(int port) +{ + void __iomem *pcie_fpga_base; + u16 reg; + + pcie_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE); + reg = in_be16(pcie_fpga_base + FPGA_REG1C); + iounmap(pcie_fpga_base); + + switch(port) { + case 0: return !(reg & FPGA_REG1C_PE0_PRSNT); + case 1: return !(reg & FPGA_REG1C_PE1_PRSNT); + case 2: return !(reg & FPGA_REG1C_PE2_PRSNT); + default: return 0; + } +} + +/* + * For the given slot, set rootpoint mode, send power to the slot, + * turn on the green LED and turn off the yellow LED, enable the clock + * and turn off reset. + */ +static void __init yucca_setup_pcie_fpga_rootpoint(int port) +{ + void __iomem *pcie_reg_fpga_base; + u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint; + + pcie_reg_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE); + + switch(port) { + case 0: + rootpoint = FPGA_REG1C_PE0_ROOTPOINT; + endpoint = 0; + power = FPGA_REG1A_PE0_PWRON; + green_led = FPGA_REG1A_PE0_GLED; + clock = FPGA_REG1A_PE0_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE0_YLED; + reset_off = FPGA_REG1C_PE0_PERST; + break; + case 1: + rootpoint = 0; + endpoint = FPGA_REG1C_PE1_ENDPOINT; + power = FPGA_REG1A_PE1_PWRON; + green_led = FPGA_REG1A_PE1_GLED; + clock = FPGA_REG1A_PE1_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE1_YLED; + reset_off = FPGA_REG1C_PE1_PERST; + break; + case 2: + rootpoint = 0; + endpoint = FPGA_REG1C_PE2_ENDPOINT; + power = FPGA_REG1A_PE2_PWRON; + green_led = FPGA_REG1A_PE2_GLED; + clock = FPGA_REG1A_PE2_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE2_YLED; + reset_off = FPGA_REG1C_PE2_PERST; + break; + + default: + return; + } + + out_be16(pcie_reg_fpga_base + FPGA_REG1A, + ~(power | clock | green_led) & + (yellow_led | in_be16(pcie_reg_fpga_base + FPGA_REG1A))); + out_be16(pcie_reg_fpga_base + FPGA_REG1C, + ~(endpoint | reset_off) & + (rootpoint | in_be16(pcie_reg_fpga_base + FPGA_REG1C))); + + /* + * Leave device in reset for a while after powering on the + * slot to give it a chance to initialize. + */ + mdelay(250); + + out_be16(pcie_reg_fpga_base + FPGA_REG1C, + reset_off | in_be16(pcie_reg_fpga_base + FPGA_REG1C)); + + iounmap(pcie_reg_fpga_base); +} + +static void __init +yucca_setup_hoses(void) +{ + struct pci_controller *hose; + char name[20]; + int i; + + if (0 && ppc440spe_init_pcie()) { + printk(KERN_WARNING "PPC440SPe PCI Express initialization failed\n"); + return; + } + + for (i = 0; i <= 2; ++i) { + if (!yucca_pcie_card_present(i)) + continue; + + printk(KERN_INFO "PCIE%d: card present\n", i); + yucca_setup_pcie_fpga_rootpoint(i); + if (ppc440spe_init_pcie_rootport(i)) { + printk(KERN_WARNING "PCIE%d: initialization failed\n", i); + continue; + } + + hose = pcibios_alloc_controller(); + if (!hose) + return; + + sprintf(name, "PCIE%d host bridge", i); + pci_init_resource(&hose->io_resource, + YUCCA_PCIX_LOWER_IO, + YUCCA_PCIX_UPPER_IO, + IORESOURCE_IO, + name); + + hose->mem_space.start = YUCCA_PCIE_LOWER_MEM + + i * YUCCA_PCIE_MEM_SIZE; + hose->mem_space.end = hose->mem_space.start + + YUCCA_PCIE_MEM_SIZE - 1; + + pci_init_resource(&hose->mem_resources[0], + hose->mem_space.start, + hose->mem_space.end, + IORESOURCE_MEM, + name); + + hose->first_busno = 0; + hose->last_busno = 15; + hose_type[hose->index] = HOSE_PCIE0 + i; + + ppc440spe_setup_pcie(hose, i); + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + } + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = yucca_map_irq; +} + +TODC_ALLOC(); + +static void __init +yucca_early_serial_map(void) +{ + struct uart_port port; + + /* Setup ioremapped serial port access */ + memset(&port, 0, sizeof(port)); + port.membase = ioremap64(PPC440SPE_UART0_ADDR, 8); + port.irq = UART0_INT; + port.uartclk = clocks.uart0; + port.regshift = 0; + port.iotype = SERIAL_IO_MEM; + port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } + + port.membase = ioremap64(PPC440SPE_UART1_ADDR, 8); + port.irq = UART1_INT; + port.uartclk = clocks.uart1; + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } + + port.membase = ioremap64(PPC440SPE_UART2_ADDR, 8); + port.irq = UART2_INT; + port.uartclk = BASE_BAUD; + port.line = 2; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 2 failed\n"); + } +} + +static void __init +yucca_setup_arch(void) +{ + yucca_set_emacdata(); + +#if !defined(CONFIG_BDI_SWITCH) + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ + mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); +#endif + + /* + * Determine various clocks. + * To be completely correct we should get SysClk + * from FPGA, because it can be changed by on-board switches + * --ebs + */ + /* 440GX and 440SPe clocking is the same - rd */ + ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ocp_sys_info.opb_bus_freq = clocks.opb; + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Setup PCIXn host bridges */ + yucca_setup_hoses(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + + yucca_early_serial_map(); + + /* Identify the system */ + printk("Yucca port (Roland Dreier )\n"); +} + +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) +{ + ibm44x_platform_init(r3, r4, r5, r6, r7); + + ppc_md.setup_arch = yucca_setup_arch; + ppc_md.show_cpuinfo = yucca_show_cpuinfo; + ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ + + ppc_md.calibrate_decr = yucca_calibrate_decr; +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = yucca_early_serial_map; +#endif +} diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h new file mode 100644 index 000000000000..01a4afea1514 --- /dev/null +++ b/arch/ppc/platforms/4xx/yucca.h @@ -0,0 +1,111 @@ +/* + * arch/ppc/platforms/4xx/yucca.h + * + * Yucca board definitions + * + * Roland Dreier (based on luan.h by Matt Porter) + * + * Copyright 2004-2005 MontaVista Software Inc. + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * 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. + * + */ + +#ifdef __KERNEL__ +#ifndef __ASM_YUCCA_H__ +#define __ASM_YUCCA_H__ + +#include +#include + +/* F/W TLB mapping used in bootloader glue to reset EMAC */ +#define PPC44x_EMAC0_MR0 0xa0000800 + +/* Location of MAC addresses in PIBS image */ +#define PIBS_FLASH_BASE 0xffe00000 +#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0x1b0400) + +/* External timer clock frequency */ +#define YUCCA_TMR_CLK 25000000 + +/* + * FPGA registers + */ +#define YUCCA_FPGA_REG_BASE 0x00000004e2000000ULL +#define YUCCA_FPGA_REG_SIZE 0x24 + +#define FPGA_REG1A 0x1a + +#define FPGA_REG1A_PE0_GLED 0x8000 +#define FPGA_REG1A_PE1_GLED 0x4000 +#define FPGA_REG1A_PE2_GLED 0x2000 +#define FPGA_REG1A_PE0_YLED 0x1000 +#define FPGA_REG1A_PE1_YLED 0x0800 +#define FPGA_REG1A_PE2_YLED 0x0400 +#define FPGA_REG1A_PE0_PWRON 0x0200 +#define FPGA_REG1A_PE1_PWRON 0x0100 +#define FPGA_REG1A_PE2_PWRON 0x0080 +#define FPGA_REG1A_PE0_REFCLK_ENABLE 0x0040 +#define FPGA_REG1A_PE1_REFCLK_ENABLE 0x0020 +#define FPGA_REG1A_PE2_REFCLK_ENABLE 0x0010 +#define FPGA_REG1A_PE_SPREAD0 0x0008 +#define FPGA_REG1A_PE_SPREAD1 0x0004 +#define FPGA_REG1A_PE_SELSOURCE_0 0x0002 +#define FPGA_REG1A_PE_SELSOURCE_1 0x0001 + +#define FPGA_REG1C 0x1c + +#define FPGA_REG1C_PE0_ROOTPOINT 0x8000 +#define FPGA_REG1C_PE1_ENDPOINT 0x4000 +#define FPGA_REG1C_PE2_ENDPOINT 0x2000 +#define FPGA_REG1C_PE0_PRSNT 0x1000 +#define FPGA_REG1C_PE1_PRSNT 0x0800 +#define FPGA_REG1C_PE2_PRSNT 0x0400 +#define FPGA_REG1C_PE0_WAKE 0x0080 +#define FPGA_REG1C_PE1_WAKE 0x0040 +#define FPGA_REG1C_PE2_WAKE 0x0020 +#define FPGA_REG1C_PE0_PERST 0x0010 +#define FPGA_REG1C_PE1_PERST 0x0008 +#define FPGA_REG1C_PE2_PERST 0x0004 + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 3 + +/* PIBS defined UART mappings, used before early_serial_setup */ +#define UART0_IO_BASE 0xa0000200 +#define UART1_IO_BASE 0xa0000300 +#define UART2_IO_BASE 0xa0000600 + +#define BASE_BAUD 11059200 +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_INT, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: (void*)UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) \ + STD_UART_OP(2) + +/* PCI support */ +#define YUCCA_PCIX_LOWER_IO 0x00000000 +#define YUCCA_PCIX_UPPER_IO 0x0000ffff +#define YUCCA_PCIX_LOWER_MEM 0x80000000 +#define YUCCA_PCIX_UPPER_MEM 0x8fffffff +#define YUCCA_PCIE_LOWER_MEM 0x90000000 +#define YUCCA_PCIE_MEM_SIZE 0x10000000 + +#define YUCCA_PCIX_MEM_SIZE 0x10000000 +#define YUCCA_PCIX_MEM_OFFSET 0x00000000 +#define YUCCA_PCIE_MEM_SIZE 0x10000000 +#define YUCCA_PCIE_MEM_OFFSET 0x00000000 + +#endif /* __ASM_YUCCA_H__ */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 13dff1e51f15..dcd168f9a7aa 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_GT64260) += gt64260_pic.o obj-$(CONFIG_LOPEC) += pci_auto.o todc_time.o obj-$(CONFIG_HDPU) += pci_auto.o obj-$(CONFIG_LUAN) += pci_auto.o todc_time.o +obj-$(CONFIG_YUCCA) += pci_auto.o todc_time.o obj-$(CONFIG_KATANA) += pci_auto.o obj-$(CONFIG_MV64360) += mv64360_pic.o obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index e992369cb8e9..6c28ae7807f4 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -97,6 +97,10 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, #include #endif +#if defined(CONFIG_YUCCA) +#include +#endif + #if defined(CONFIG_OCOTEA) #include #endif -- cgit v1.2.3 From 3e9e7c1d0b7a36fb8affb973a054c5098e27baa8 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 00:58:15 -0800 Subject: [PATCH] ppc32: cleanup AMCC PPC40x eval boards to support U-Boot Cleanup PPC40x eval boards (bubinga, walnut and sycamore) to support U-Boot as bootloader. The OpenBIOS bd_info struct is not used in the kernel anymore (only U-Boot now). uImage (U-Boot) tested on walnut, sycamore and bubinga zImage (OpenBIOS) tested on sycamore, bubinga and ebony Signed-off-by: Stefan Roese Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/simple/Makefile | 21 +++++++- arch/ppc/boot/simple/misc.c | 16 ++++-- arch/ppc/boot/simple/openbios.c | 106 +++++++++++++++++++++++++++++++++++--- arch/ppc/platforms/4xx/Kconfig | 2 +- arch/ppc/platforms/4xx/bubinga.c | 2 +- arch/ppc/platforms/4xx/bubinga.h | 64 ++++++++++------------- arch/ppc/platforms/4xx/ebony.h | 4 +- arch/ppc/platforms/4xx/sycamore.c | 7 +-- arch/ppc/platforms/4xx/sycamore.h | 67 ++++++++++-------------- arch/ppc/platforms/4xx/walnut.c | 2 +- arch/ppc/platforms/4xx/walnut.h | 67 +++++++++--------------- include/asm-ppc/ibm_ocp.h | 19 +++++-- include/asm-ppc/ppcboot.h | 6 ++- 13 files changed, 237 insertions(+), 146 deletions(-) (limited to 'include') diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index ff0904ee889d..82df88b01bbe 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -67,6 +67,12 @@ zimageinitrd-$(CONFIG_BAMBOO) := zImage.initrd-TREE entrypoint-$(CONFIG_BAMBOO) := 0x01000000 extra.o-$(CONFIG_BAMBOO) := pibs.o + zimage-$(CONFIG_BUBINGA) := zImage-TREE +zimageinitrd-$(CONFIG_BUBINGA) := zImage.initrd-TREE + end-$(CONFIG_BUBINGA) := bubinga + entrypoint-$(CONFIG_BUBINGA) := 0x01000000 + extra.o-$(CONFIG_BUBINGA) := openbios.o + zimage-$(CONFIG_EBONY) := zImage-TREE zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE end-$(CONFIG_EBONY) := ebony @@ -91,6 +97,18 @@ zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE entrypoint-$(CONFIG_OCOTEA) := 0x01000000 extra.o-$(CONFIG_OCOTEA) := pibs.o + zimage-$(CONFIG_SYCAMORE) := zImage-TREE +zimageinitrd-$(CONFIG_SYCAMORE) := zImage.initrd-TREE + end-$(CONFIG_SYCAMORE) := sycamore + entrypoint-$(CONFIG_SYCAMORE) := 0x01000000 + extra.o-$(CONFIG_SYCAMORE) := openbios.o + + zimage-$(CONFIG_WALNUT) := zImage-TREE +zimageinitrd-$(CONFIG_WALNUT) := zImage.initrd-TREE + end-$(CONFIG_WALNUT) := walnut + entrypoint-$(CONFIG_WALNUT) := 0x01000000 + extra.o-$(CONFIG_WALNUT) := openbios.o + extra.o-$(CONFIG_EV64260) := misc-ev64260.o end-$(CONFIG_EV64260) := ev64260 cacheflag-$(CONFIG_EV64260) := -include $(clear_L2_L3) @@ -168,7 +186,8 @@ OBJCOPY_ARGS := -O elf32-powerpc # head.o and relocate.o must be at the start. boot-y := head.o relocate.o $(extra.o-y) $(misc-y) -boot-$(CONFIG_40x) += embed_config.o +boot-$(CONFIG_REDWOOD_5) += embed_config.o +boot-$(CONFIG_REDWOOD_6) += embed_config.o boot-$(CONFIG_8xx) += embed_config.o boot-$(CONFIG_8260) += embed_config.o boot-$(CONFIG_BSEIP) += iic.o diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c index e02de5b467a4..f415d6c62362 100644 --- a/arch/ppc/boot/simple/misc.c +++ b/arch/ppc/boot/simple/misc.c @@ -23,7 +23,7 @@ #include #include #include -#ifdef CONFIG_44x +#ifdef CONFIG_4xx #include #endif #include @@ -88,6 +88,14 @@ get_mem_size(void) return 0; } +#if defined(CONFIG_40x) +#define PPC4xx_EMAC0_MR0 EMAC0_BASE +#endif + +#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0) +#define PPC4xx_EMAC0_MR0 PPC44x_EMAC0_MR0 +#endif + struct bi_record * decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) { @@ -103,13 +111,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) com_port = serial_init(0, NULL); #endif -#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0) +#if defined(PPC4xx_EMAC0_MR0) /* Reset MAL */ mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* Wait for reset */ while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* Reset EMAC */ - *(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000; + *(volatile unsigned long *)PPC4xx_EMAC0_MR0 = 0x20000000; __asm__ __volatile__("eieio"); #endif @@ -164,7 +172,9 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); } +#ifndef CONFIG_40x /* don't overwrite the 40x image located at 0x00400000! */ avail_ram = (char *)0x00400000; +#endif end_avail = (char *)0x00800000; puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c index c732b6d70cfb..81f11d8b30a7 100644 --- a/arch/ppc/boot/simple/openbios.c +++ b/arch/ppc/boot/simple/openbios.c @@ -1,19 +1,43 @@ /* * arch/ppc/boot/simple/openbios.c * - * 2005 (c) SYSGO AG - g.jaeger@sysgo.com + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese + * + * Based on original work by + * 2005 (c) SYSGO AG - g.jaeger@sysgo.com + * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without * any warranty of any kind, whether express or implied. * - * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista) */ #include #include #include #include -#include +#include +#include +#ifdef CONFIG_40x +#include +#endif + +#if defined(CONFIG_BUBINGA) +#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */ +#else +#define BOARD_INFO_VECTOR 0xFFFE0B50 +#endif + +#ifdef CONFIG_40x +/* Supply a default Ethernet address for those eval boards that don't + * ship with one. This is an address from the MBX board I have, so + * it is unlikely you will find it on your network. + */ +static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; + +extern unsigned long timebase_period_ns; +#endif /* CONFIG_40x */ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum); @@ -23,15 +47,85 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot"))); bd_t *hold_residual = &hold_resid_buf; +typedef struct openbios_board_info { + unsigned char bi_s_version[4]; /* Version of this structure */ + unsigned char bi_r_version[30]; /* Version of the IBM ROM */ + unsigned int bi_memsize; /* DRAM installed, in bytes */ +#ifdef CONFIG_405EP + unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ +#else /* CONFIG_405EP */ + unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ +#endif /* CONFIG_405EP */ + unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ + unsigned int bi_intfreq; /* Processor speed, in Hz */ + unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ + unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ +#ifdef CONFIG_405EP + unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */ + unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */ +#endif /* CONFIG_405EP */ +} openbios_bd_t; + void * load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, void *ign1, void *ign2) { - decompress_kernel(load_addr, num_words, cksum); +#ifdef CONFIG_40x + openbios_bd_t *openbios_bd = NULL; + openbios_bd_t *(*get_board_info)(void) = + (openbios_bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); + + /* + * On 40x platforms we not only need the MAC-addresses, but also the + * clocks and memsize. Now try to get all values using the OpenBIOS + * "get_board_info()" callback. + */ + if ((openbios_bd = get_board_info()) != NULL) { + /* + * Copy bd_info from OpenBIOS struct into U-Boot struct + * used by kernel + */ + hold_residual->bi_memsize = openbios_bd->bi_memsize; + hold_residual->bi_intfreq = openbios_bd->bi_intfreq; + hold_residual->bi_busfreq = openbios_bd->bi_busfreq; + hold_residual->bi_pci_busfreq = openbios_bd->bi_pci_busfreq; + memcpy(hold_residual->bi_pci_enetaddr, openbios_bd->bi_pci_enetaddr, 6); +#ifdef CONFIG_405EP + memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr[0], 6); + memcpy(hold_residual->bi_enet1addr, openbios_bd->bi_enetaddr[1], 6); + hold_residual->bi_opbfreq = openbios_bd->bi_opb_busfreq; + hold_residual->bi_procfreq = openbios_bd->bi_pllouta_freq; +#else /* CONFIG_405EP */ + memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr, 6); +#endif /* CONFIG_405EP */ + } else { + /* Hmmm...better try to stuff some defaults. + */ + hold_residual->bi_memsize = 16 * 1024 * 1024; + hold_residual->bi_intfreq = 200000000; + hold_residual->bi_busfreq = 100000000; + hold_residual->bi_pci_busfreq = 66666666; + + /* + * Only supply one mac-address in this fallback + */ + memcpy(hold_residual->bi_enetaddr, (void *)def_enet_addr, 6); +#ifdef CONFIG_405EP + hold_residual->bi_opbfreq = 50000000; + hold_residual->bi_procfreq = 200000000; +#endif /* CONFIG_405EP */ + } + timebase_period_ns = 1000000000 / hold_residual->bi_intfreq; +#endif /* CONFIG_40x */ + +#ifdef CONFIG_440GP /* simply copy the MAC addresses */ - memcpy(hold_residual->bi_enetaddr, (char *)EBONY_OPENBIOS_MAC_BASE, 6); - memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6); + memcpy(hold_residual->bi_enetaddr, (char *)OPENBIOS_MAC_BASE, 6); + memcpy(hold_residual->bi_enet1addr, (char *)(OPENBIOS_MAC_BASE+OPENBIOS_MAC_OFFSET), 6); +#endif /* CONFIG_440GP */ + + decompress_kernel(load_addr, num_words, cksum); return (void *)hold_residual; } diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index e70e4c6ec787..d8837911bbc6 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -225,7 +225,7 @@ config EMBEDDEDBOOT config IBM_OPENBIOS bool - depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || REDWOOD_5 || REDWOOD_6 default y config PPC4xx_DMA diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c index 3678abf86313..8110f55668c5 100644 --- a/arch/ppc/platforms/4xx/bubinga.c +++ b/arch/ppc/platforms/4xx/bubinga.c @@ -89,7 +89,7 @@ bubinga_early_serial_map(void) * by 16. */ uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV); - uart_clock = __res.bi_pllouta_freq / uart_div; + uart_clock = __res.bi_procfreq / uart_div; /* Setup serial port access */ memset(&port, 0, sizeof(port)); diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h index b1df856f8e22..b5380cfaf5c0 100644 --- a/arch/ppc/platforms/4xx/bubinga.h +++ b/arch/ppc/platforms/4xx/bubinga.h @@ -1,52 +1,34 @@ /* - * Support for IBM PPC 405EP evaluation board (Bubinga). + * arch/ppc/platforms/4xx/bubinga.h * - * Author: SAW (IBM), derived from walnut.h. - * Maintained by MontaVista Software + * Bubinga board definitions + * + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese + * + * Based on original work by + * SAW (IBM) + * 2003 (c) MontaVista Softare Inc. + * + * 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. * - * 2003 (c) MontaVista Softare Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is - * licensed "as is" without any warranty of any kind, whether express - * or implied. */ #ifdef __KERNEL__ #ifndef __BUBINGA_H__ #define __BUBINGA_H__ -/* 405EP */ +#include #include - -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ - unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */ - unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - +#include /* Memory map for the Bubinga board. * Generic 4xx plus RTC. */ -extern void *bubinga_rtc_base; #define BUBINGA_RTC_PADDR ((uint)0xf0000000) #define BUBINGA_RTC_VADDR BUBINGA_RTC_PADDR #define BUBINGA_RTC_SIZE ((uint)8*1024) @@ -58,12 +40,18 @@ extern void *bubinga_rtc_base; * for typical configurations at various CPU speeds. * The base baud is calculated as (FWDA / EXT UART DIV / 16) */ -#define BASE_BAUD 0 +#define BASE_BAUD 0 -#define BUBINGA_FPGA_BASE 0xF0300000 +/* Flash */ +#define PPC40x_FPGA_BASE 0xF0300000 +#define PPC40x_FPGA_REG_OFFS 1 /* offset to flash map reg */ +#define PPC40x_FLASH_ONBD_N(x) (x & 0x02) +#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01) +#define PPC40x_FLASH_LOW 0xFFF00000 +#define PPC40x_FLASH_HIGH 0xFFF80000 +#define PPC40x_FLASH_SIZE 0x80000 -#define PPC4xx_MACHINE_NAME "IBM Bubinga" +#define PPC4xx_MACHINE_NAME "IBM Bubinga" -#endif /* !__ASSEMBLY__ */ #endif /* __BUBINGA_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index d08faa46a0ae..b91ad4272dfe 100644 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -24,8 +24,8 @@ #define PPC44x_EMAC0_MR0 0xE0000800 /* Where to find the MAC info */ -#define EBONY_OPENBIOS_MAC_BASE 0xfffffe0c -#define EBONY_OPENBIOS_MAC_OFFSET 0x0c +#define OPENBIOS_MAC_BASE 0xfffffe0c +#define OPENBIOS_MAC_OFFSET 0x0c /* Default clock rates for Rev. B and Rev. C silicon */ #define EBONY_440GP_RB_SYSCLK 33000000 diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c index d8019eec4704..281b4a2ffb96 100644 --- a/arch/ppc/platforms/4xx/sycamore.c +++ b/arch/ppc/platforms/4xx/sycamore.c @@ -88,9 +88,6 @@ ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) void __init sycamore_setup_arch(void) { -#define SYCAMORE_PS2_BASE 0xF0100000 -#define SYCAMORE_FPGA_BASE 0xF0300000 - void *fpga_brdc; unsigned char fpga_brdc_data; void *fpga_enable; @@ -100,7 +97,7 @@ sycamore_setup_arch(void) ppc4xx_setup_arch(); - ibm_ocp_set_emac(0, 1); + ibm_ocp_set_emac(0, 0); kb_data = ioremap(SYCAMORE_PS2_BASE, 8); if (!kb_data) { @@ -111,7 +108,7 @@ sycamore_setup_arch(void) kb_cs = kb_data + 1; - fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8); + fpga_status = ioremap(PPC40x_FPGA_BASE, 8); if (!fpga_status) { printk(KERN_CRIT "sycamore_setup_arch() fpga_status ioremap failed\n"); diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h index 3e7b4e2c8c57..1cd6c824fd62 100644 --- a/arch/ppc/platforms/4xx/sycamore.h +++ b/arch/ppc/platforms/4xx/sycamore.h @@ -1,67 +1,52 @@ /* * arch/ppc/platforms/4xx/sycamore.h * - * Macros, definitions, and data structures specific to the IBM PowerPC - * 405GPr "Sycamore" evaluation board. + * Sycamore board definitions * - * Author: Armin Kuster + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese + * + * Based on original work by + * Armin Kuster + * 2000 (c) MontaVista, Software, Inc. + * + * 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. * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. */ #ifdef __KERNEL__ #ifndef __ASM_SYCAMORE_H__ #define __ASM_SYCAMORE_H__ +#include #include +#include -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's "Sycamore" evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - - -/* Memory map for the IBM "Sycamore" 405GP evaluation board. +/* Memory map for the IBM "Sycamore" 405GPr evaluation board. * Generic 4xx plus RTC. */ -extern void *sycamore_rtc_base; #define SYCAMORE_RTC_PADDR ((uint)0xf0000000) #define SYCAMORE_RTC_VADDR SYCAMORE_RTC_PADDR -#define SYCAMORE_RTC_SIZE ((uint)8*1024) +#define SYCAMORE_RTC_SIZE ((uint)8*1024) -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else #define BASE_BAUD 691200 -#endif -#define SYCAMORE_PS2_BASE 0xF0100000 -#define SYCAMORE_FPGA_BASE 0xF0300000 +#define SYCAMORE_PS2_BASE 0xF0100000 + +/* Flash */ +#define PPC40x_FPGA_BASE 0xF0300000 +#define PPC40x_FPGA_REG_OFFS 5 /* offset to flash map reg */ +#define PPC40x_FLASH_ONBD_N(x) (x & 0x02) +#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01) +#define PPC40x_FLASH_LOW 0xFFF00000 +#define PPC40x_FLASH_HIGH 0xFFF80000 +#define PPC40x_FLASH_SIZE 0x80000 #define PPC4xx_MACHINE_NAME "IBM Sycamore" -#endif /* !__ASSEMBLY__ */ #endif /* __ASM_SYCAMORE_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c index a33eda4b7489..74cb33182d9f 100644 --- a/arch/ppc/platforms/4xx/walnut.c +++ b/arch/ppc/platforms/4xx/walnut.c @@ -90,7 +90,7 @@ walnut_setup_arch(void) kb_cs = kb_data + 1; - fpga_status = ioremap(WALNUT_FPGA_BASE, 8); + fpga_status = ioremap(PPC40x_FPGA_BASE, 8); if (!fpga_status) { printk(KERN_CRIT "walnut_setup_arch() fpga_status ioremap failed\n"); diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h index 04cfbf3696b9..dcf2691698c0 100644 --- a/arch/ppc/platforms/4xx/walnut.h +++ b/arch/ppc/platforms/4xx/walnut.h @@ -1,72 +1,55 @@ /* * arch/ppc/platforms/4xx/walnut.h * - * Macros, definitions, and data structures specific to the IBM PowerPC - * 405GP "Walnut" evaluation board. + * Walnut board definitions * - * Authors: Grant Erickson , Frank Rowand - * , Debbie Chu or - * source@mvista.com + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese * - * Copyright (c) 1999 Grant Erickson + * Based on original work by + * Copyright (c) 1999 Grant Erickson + * Frank Rowand + * Debbie Chu + * 2000 (c) MontaVista, Software, Inc. + * + * 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. * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. */ #ifdef __KERNEL__ #ifndef __ASM_WALNUT_H__ #define __ASM_WALNUT_H__ -/* We have a 405GP core */ +#include #include - -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's "Walnut" evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - +#include /* Memory map for the IBM "Walnut" 405GP evaluation board. * Generic 4xx plus RTC. */ -extern void *walnut_rtc_base; #define WALNUT_RTC_PADDR ((uint)0xf0000000) #define WALNUT_RTC_VADDR WALNUT_RTC_PADDR #define WALNUT_RTC_SIZE ((uint)8*1024) -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else #define BASE_BAUD 691200 -#endif #define WALNUT_PS2_BASE 0xF0100000 -#define WALNUT_FPGA_BASE 0xF0300000 + +/* Flash */ +#define PPC40x_FPGA_BASE 0xF0300000 +#define PPC40x_FPGA_REG_OFFS 5 /* offset to flash map reg */ +#define PPC40x_FLASH_ONBD_N(x) (x & 0x02) +#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01) +#define PPC40x_FLASH_LOW 0xFFF00000 +#define PPC40x_FLASH_HIGH 0xFFF80000 +#define PPC40x_FLASH_SIZE 0x80000 +#define WALNUT_FPGA_BASE PPC40x_FPGA_BASE #define PPC4xx_MACHINE_NAME "IBM Walnut" -#endif /* !__ASSEMBLY__ */ #endif /* __ASM_WALNUT_H__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h index 6f10a25bd628..9c21de1ff4ed 100644 --- a/include/asm-ppc/ibm_ocp.h +++ b/include/asm-ppc/ibm_ocp.h @@ -131,9 +131,22 @@ static inline void ibm_ocp_set_emac(int start, int end) /* Copy MAC addresses to EMAC additions */ for (i=start; i<=end; i++) { def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i); - memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, - &__res.bi_enetaddr[i], - 6); + if (i == 0) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enetaddr, 6); +#if defined(CONFIG_405EP) || defined(CONFIG_44x) + else if (i == 1) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enet1addr, 6); +#endif +#if defined(CONFIG_440GX) + else if (i == 2) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enet2addr, 6); + else if (i == 3) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enet3addr, 6); +#endif } } #endif diff --git a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h index fe24e4520208..6b7b63f71daa 100644 --- a/include/asm-ppc/ppcboot.h +++ b/include/asm-ppc/ppcboot.h @@ -73,8 +73,8 @@ typedef struct bd_info { #if defined(CONFIG_HYMOD) hymod_conf_t bi_hymod_conf; /* hymod configuration information */ #endif -#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx) ||\ - defined(CONFIG_83xx) +#if defined(CONFIG_EVB64260) || defined(CONFIG_405EP) || defined(CONFIG_44x) || \ + defined(CONFIG_85xx) || defined(CONFIG_83xx) /* second onboard ethernet port */ unsigned char bi_enet1addr[6]; #endif @@ -96,5 +96,7 @@ typedef struct bd_info { #endif } bd_t; +#define bi_tbfreq bi_intfreq + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PPCBOOT_H__ */ -- cgit v1.2.3 From 055a2512144cd7e60dcaae7a13e460df43b98787 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:21 -0800 Subject: [PATCH] superhyway: multiple block support and VCR rework This extends the API somewhat to allow for platform-specific VCR reading and writing. Some platforms (like SH4-202) implement the VCR in a split VCRL and VCRH, but end up being in reverse order or have other quirks that need to be dealt with, so we add a set of superhyway_ops per-bus to accomodate this. We also have to extend the per-device resources somewhat, as some devices now conveniently split control and data blocks. So we allow a platform to register its set of SuperHyway devices via superhyway_add_devices() with the control block always ordered as the first resource (as this is the one that userspace cares about). Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/sh/superhyway/superhyway-sysfs.c | 2 +- drivers/sh/superhyway/superhyway.c | 75 +++++++++++++++++++++++--------- include/linux/superhyway.h | 38 +++++++++++++--- 3 files changed, 89 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c index dc119ce68e3e..55434330867b 100644 --- a/drivers/sh/superhyway/superhyway-sysfs.c +++ b/drivers/sh/superhyway/superhyway-sysfs.c @@ -30,7 +30,7 @@ superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb); superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb); /* Misc */ -superhyway_ro_attr(resource, "0x%08lx\n", resource.start); +superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start); struct device_attribute superhyway_dev_attrs[] = { __ATTR_RO(perr_flags), diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 28757cb9d246..7bdab2a7f59c 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -27,19 +27,20 @@ static struct device superhyway_bus_device = { static void superhyway_device_release(struct device *dev) { - kfree(to_superhyway_device(dev)); + struct superhyway_device *sdev = to_superhyway_device(dev); + + kfree(sdev->resource); + kfree(sdev); } /** * superhyway_add_device - Add a SuperHyway module - * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID). * @base: Physical address where module is mapped. - * @vcr: VCR value. + * @sdev: SuperHyway device to add, or NULL to allocate a new one. + * @bus: Bus where SuperHyway module resides. * * This is responsible for adding a new SuperHyway module. This sets up a new - * struct superhyway_device for the module being added. Each one of @mod_id, - * @base, and @vcr are registered with the new device for further use - * elsewhere. + * struct superhyway_device for the module being added if @sdev == NULL. * * Devices are initially added in the order that they are scanned (from the * top-down of the memory map), and are assigned an ID based on the order that @@ -49,28 +50,40 @@ static void superhyway_device_release(struct device *dev) * Further work can and should be done in superhyway_scan_bus(), to be sure * that any new modules are properly discovered and subsequently registered. */ -int superhyway_add_device(unsigned int mod_id, unsigned long base, - unsigned long long vcr) +int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, + struct superhyway_bus *bus) { - struct superhyway_device *dev; + struct superhyway_device *dev = sdev; + + if (!dev) { + dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL); + if (!dev) + return -ENOMEM; - dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL); - if (!dev) - return -ENOMEM; + memset(dev, 0, sizeof(struct superhyway_device)); + } - memset(dev, 0, sizeof(struct superhyway_device)); + dev->bus = bus; + superhyway_read_vcr(dev, base, &dev->vcr); - dev->id.id = mod_id; - sprintf(dev->name, "SuperHyway device %04x", dev->id.id); + if (!dev->resource) { + dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL); + if (!dev->resource) { + kfree(dev); + return -ENOMEM; + } + + dev->resource->name = dev->name; + dev->resource->start = base; + dev->resource->end = dev->resource->start + 0x01000000; + } - dev->vcr = *((struct vcr_info *)(&vcr)); - dev->resource.name = dev->name; - dev->resource.start = base; - dev->resource.end = dev->resource.start + 0x01000000; dev->dev.parent = &superhyway_bus_device; dev->dev.bus = &superhyway_bus_type; dev->dev.release = superhyway_device_release; + dev->id.id = dev->vcr.mod_id; + sprintf(dev->name, "SuperHyway device %04x", dev->id.id); sprintf(dev->dev.bus_id, "%02x", superhyway_devices); superhyway_devices++; @@ -78,10 +91,31 @@ int superhyway_add_device(unsigned int mod_id, unsigned long base, return device_register(&dev->dev); } +int superhyway_add_devices(struct superhyway_bus *bus, + struct superhyway_device **devices, + int nr_devices) +{ + int i, ret = 0; + + for (i = 0; i < nr_devices; i++) { + struct superhyway_device *dev = devices[i]; + ret |= superhyway_add_device(dev->resource[0].start, dev, bus); + } + + return ret; +} + static int __init superhyway_init(void) { + struct superhyway_bus *bus; + int ret = 0; + device_register(&superhyway_bus_device); - return superhyway_scan_bus(); + + for (bus = superhyway_channels; bus->ops; bus++) + ret |= superhyway_scan_bus(bus); + + return ret; } postcore_initcall(superhyway_init); @@ -197,6 +231,7 @@ module_exit(superhyway_bus_exit); EXPORT_SYMBOL(superhyway_bus_type); EXPORT_SYMBOL(superhyway_add_device); +EXPORT_SYMBOL(superhyway_add_devices); EXPORT_SYMBOL(superhyway_register_driver); EXPORT_SYMBOL(superhyway_unregister_driver); diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h index c906c5a0aaef..17ea468fa362 100644 --- a/include/linux/superhyway.h +++ b/include/linux/superhyway.h @@ -19,7 +19,7 @@ */ #define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183 -struct vcr_info { +struct superhyway_vcr_info { u8 perr_flags; /* P-port Error flags */ u8 merr_flags; /* Module Error flags */ u16 mod_vers; /* Module Version */ @@ -28,6 +28,17 @@ struct vcr_info { u8 top_mb; /* Top Memory block */ }; +struct superhyway_ops { + int (*read_vcr)(unsigned long base, struct superhyway_vcr_info *vcr); + int (*write_vcr)(unsigned long base, struct superhyway_vcr_info vcr); +}; + +struct superhyway_bus { + struct superhyway_ops *ops; +}; + +extern struct superhyway_bus superhyway_channels[]; + struct superhyway_device_id { unsigned int id; unsigned long driver_data; @@ -55,9 +66,11 @@ struct superhyway_device { struct superhyway_device_id id; struct superhyway_driver *drv; + struct superhyway_bus *bus; - struct resource resource; - struct vcr_info vcr; + int num_resources; + struct resource *resource; + struct superhyway_vcr_info vcr; }; #define to_superhyway_device(d) container_of((d), struct superhyway_device, dev) @@ -65,12 +78,27 @@ struct superhyway_device { #define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev) #define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p)) -extern int superhyway_scan_bus(void); +static inline int +superhyway_read_vcr(struct superhyway_device *dev, unsigned long base, + struct superhyway_vcr_info *vcr) +{ + return dev->bus->ops->read_vcr(base, vcr); +} + +static inline int +superhyway_write_vcr(struct superhyway_device *dev, unsigned long base, + struct superhyway_vcr_info vcr) +{ + return dev->bus->ops->write_vcr(base, vcr); +} + +extern int superhyway_scan_bus(struct superhyway_bus *); /* drivers/sh/superhyway/superhyway.c */ int superhyway_register_driver(struct superhyway_driver *); void superhyway_unregister_driver(struct superhyway_driver *); -int superhyway_add_device(unsigned int, unsigned long, unsigned long long); +int superhyway_add_device(unsigned long base, struct superhyway_device *, struct superhyway_bus *); +int superhyway_add_devices(struct superhyway_bus *bus, struct superhyway_device **devices, int nr_devices); /* drivers/sh/superhyway/superhyway-sysfs.c */ extern struct device_attribute superhyway_dev_attrs[]; -- cgit v1.2.3 From d229401f130941583eb46a2e8886df61241c14eb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:23 -0800 Subject: [PATCH] sh: pte_mkhuge() compile fix for !CONFIG_HUGETLB_PAGE Presently it is bogus to call pte_mkhuge() outside of the CONFIG_HUGETLB_PAGE context, as the only processors that support _PAGE_SZHUGE do so in the hugetlbpage context only (and this is the only time that _PAGE_SZHUGE is even defined). SH-2 and SH-3 do not support huge pages at all, and so it is not possible to enable this. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-sh/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index aef8ae43de13..dee36bcbcf98 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -196,7 +196,9 @@ static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _ static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } +#ifdef CONFIG_HUGETLB_PAGE static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; } +#endif /* * Macro and implementation to make a page protection as uncachable. -- cgit v1.2.3 From 65463b73b14ed43368dc5961a6c3dcb0d98cfe1f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:24 -0800 Subject: [PATCH] sh: Drop hp690 discontig support There was only one board using this (hp690 specifically), and it just so happens that it's only physically discontiguous at the "normal" P1 offset. If we bump up the P1 offset, it's possible to hit a shadowed region of memory where we suddenly become magically contiguous. As people have been using this shadowed region workaround for quite some time (and without any adverse effects), it's time to drop the left over discontig bits that no longer have any practical use (it was always very much hp690-centric to begin with). Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/Kconfig | 10 -------- arch/sh/kernel/setup.c | 26 ++++++--------------- arch/sh/mm/init.c | 21 ++--------------- include/asm-sh/mmzone.h | 61 ------------------------------------------------- include/asm-sh/page.h | 7 ------ 5 files changed, 9 insertions(+), 116 deletions(-) delete mode 100644 include/asm-sh/mmzone.h (limited to 'include') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 7d31d628cdec..64f5ae0ff96d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -490,16 +490,6 @@ config CPU_SUBTYPE_ST40 depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1 default y -config ARCH_DISCONTIGMEM_ENABLE - bool - depends on SH_HP690 - default y - help - Say Y to upport efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. - source "mm/Kconfig" config ZERO_PAGE_OFFSET diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 25b9d9ebe858..036050b377cd 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -83,9 +83,9 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name); /* ... */ #define COMMAND_LINE ((char *) (PARAM+0x100)) -#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 +#define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE] = { 0, }; @@ -284,18 +284,6 @@ void __init setup_arch(char **cmdline_p) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) -#ifdef CONFIG_DISCONTIGMEM - NODE_DATA(0)->bdata = &discontig_node_bdata[0]; - NODE_DATA(1)->bdata = &discontig_node_bdata[1]; - - bootmap_size = init_bootmem_node(NODE_DATA(1), - PFN_UP(__MEMORY_START_2ND), - PFN_UP(__MEMORY_START_2ND), - PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND)); - free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND); - reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size); -#endif - /* * Find the highest page frame number we have available */ @@ -306,10 +294,10 @@ void __init setup_arch(char **cmdline_p) */ max_low_pfn = max_pfn; - /* + /* * Partially used pages are not usable - thus * we are rounding upwards: - */ + */ start_pfn = PFN_UP(__pa(_end)); /* @@ -360,12 +348,12 @@ void __init setup_arch(char **cmdline_p) reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); #ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - if (&__rd_start != &__rd_end) { + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + if (&__rd_start != &__rd_end) { LOADER_TYPE = 1; INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START; INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start; - } + } if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 4e9c854845a4..e342565f75fb 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -51,11 +51,6 @@ unsigned long mmu_context_cache = NO_CONTEXT; #define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) #endif -#ifdef CONFIG_DISCONTIGMEM -pg_data_t discontig_page_data[MAX_NUMNODES]; -bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; -#endif - void (*copy_page)(void *from, void *to); void (*clear_page)(void *to); @@ -216,15 +211,6 @@ void __init paging_init(void) #endif NODE_DATA(0)->node_mem_map = NULL; free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); - -#ifdef CONFIG_DISCONTIGMEM - /* - * And for discontig, do some more fixups on the zone sizes.. - */ - zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; - zones_size[ZONE_NORMAL] = 0; - free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); -#endif } void __init mem_init(void) @@ -248,7 +234,7 @@ void __init mem_init(void) memset(empty_zero_page, 0, PAGE_SIZE); __flush_wback_region(empty_zero_page, PAGE_SIZE); - /* + /* * Setup wrappers for copy/clear_page(), these will get overridden * later in the boot process if a better method is available. */ @@ -257,9 +243,6 @@ void __init mem_init(void) /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem_node(NODE_DATA(0)); -#ifdef CONFIG_DISCONTIGMEM - totalram_pages += free_all_bootmem_node(NODE_DATA(1)); -#endif reservedpages = 0; for (tmp = 0; tmp < num_physpages; tmp++) /* @@ -286,7 +269,7 @@ void __init mem_init(void) void free_initmem(void) { unsigned long addr; - + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h deleted file mode 100644 index 0e7406601fdf..000000000000 --- a/include/asm-sh/mmzone.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * linux/include/asm-sh/mmzone.h - * - * 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. - */ -#ifndef __ASM_SH_MMZONE_H -#define __ASM_SH_MMZONE_H - -#include - -#ifdef CONFIG_DISCONTIGMEM - -/* Currently, just for HP690 */ -#define PHYSADDR_TO_NID(phys) ((((phys) - __MEMORY_START) >= 0x01000000)?1:0) - -extern pg_data_t discontig_page_data[MAX_NUMNODES]; -extern bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; - -/* - * Following are macros that each numa implmentation must define. - */ - -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define KVADDR_TO_NID(kaddr) PHYSADDR_TO_NID(__pa(kaddr)) - -/* - * Return a pointer to the node data for node n. - */ -#define NODE_DATA(nid) (&discontig_page_data[nid]) - -/* - * NODE_MEM_MAP gives the kaddr for the mem_map of the node. - */ -#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map) - -#define phys_to_page(phys) \ -({ unsigned int node = PHYSADDR_TO_NID(phys); \ - NODE_MEM_MAP(node) \ - + (((phys) - NODE_DATA(node)->node_start_paddr) >> PAGE_SHIFT); }) - -static inline int is_valid_page(struct page *page) -{ - unsigned int i; - - for (i = 0; i < MAX_NUMNODES; i++) { - if (page >= NODE_MEM_MAP(i) && - page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size) - return 1; - } - return 0; -} - -#define VALID_PAGE(page) is_valid_page(page) -#define page_to_phys(page) PHYSADDR(page_address(page)) - -#endif /* CONFIG_DISCONTIGMEM */ -#endif diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 324e6cc5ecf7..972c3f655b2a 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -93,11 +93,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define __MEMORY_START CONFIG_MEMORY_START #define __MEMORY_SIZE CONFIG_MEMORY_SIZE -#ifdef CONFIG_DISCONTIGMEM -/* Just for HP690, for now.. */ -#define __MEMORY_START_2ND (__MEMORY_START+0x02000000) -#define __MEMORY_SIZE_2ND 0x001000000 /* 16MB */ -#endif #define PAGE_OFFSET (0x80000000UL) #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) @@ -105,10 +100,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM #define phys_to_page(phys) (mem_map + (((phys)-__MEMORY_START) >> PAGE_SHIFT)) #define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + __MEMORY_START) -#endif /* PFN start number, because of __MEMORY_START */ #define PFN_START (__MEMORY_START >> PAGE_SHIFT) -- cgit v1.2.3 From 31ab269a0307d8725737dfbbdeb5dcde7b41bc36 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 7 Nov 2005 00:58:42 -0800 Subject: [PATCH] x86: add MCE resume It's widely seen a MCE non-fatal error reported after resume. It seems MCE resume is lacked under ia32. This patch tries to fix the gap. Signed-off-by: Shaohua Li Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 5 +---- arch/i386/kernel/cpu/mcheck/k7.c | 2 +- arch/i386/kernel/cpu/mcheck/mce.c | 4 ++-- arch/i386/kernel/cpu/mcheck/p4.c | 4 ++-- arch/i386/kernel/cpu/mcheck/p5.c | 2 +- arch/i386/kernel/cpu/mcheck/p6.c | 2 +- arch/i386/kernel/cpu/mcheck/winchip.c | 2 +- arch/i386/power/cpu.c | 1 + include/asm-i386/processor.h | 6 ++++++ 9 files changed, 16 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 74145a33cb0f..c145fb30002e 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -30,8 +30,6 @@ static int disable_x86_serial_nr __devinitdata = 1; struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; -extern void mcheck_init(struct cpuinfo_x86 *c); - extern int disable_pse; static void default_init(struct cpuinfo_x86 * c) @@ -429,9 +427,8 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) } /* Init Machine Check Exception if available. */ -#ifdef CONFIG_X86_MCE mcheck_init(c); -#endif + if (c == &boot_cpu_data) sysenter_setup(); enable_sep_cpu(); diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c index 7c6b9c73522f..fc5d5215e23d 100644 --- a/arch/i386/kernel/cpu/mcheck/k7.c +++ b/arch/i386/kernel/cpu/mcheck/k7.c @@ -68,7 +68,7 @@ static fastcall void k7_machine_check(struct pt_regs * regs, long error_code) /* AMD K7 machine check is Intel like */ -void __devinit amd_mcheck_init(struct cpuinfo_x86 *c) +void amd_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index 2cf25d2ba0f1..6170af3c271a 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c @@ -16,7 +16,7 @@ #include "mce.h" -int mce_disabled __devinitdata = 0; +int mce_disabled = 0; int nr_mce_banks; EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ @@ -31,7 +31,7 @@ static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_ void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; /* This has to be run for each processor */ -void __devinit mcheck_init(struct cpuinfo_x86 *c) +void mcheck_init(struct cpuinfo_x86 *c) { if (mce_disabled==1) return; diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index 1d1e885f500a..fd2c459a31ef 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c @@ -77,7 +77,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs) } /* P4/Xeon Thermal regulation detect and init */ -static void __devinit intel_init_thermal(struct cpuinfo_x86 *c) +static void intel_init_thermal(struct cpuinfo_x86 *c) { u32 l, h; unsigned int cpu = smp_processor_id(); @@ -231,7 +231,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) } -void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c) +void intel_p4_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c index 3a2e24baddc7..94bc43d950cf 100644 --- a/arch/i386/kernel/cpu/mcheck/p5.c +++ b/arch/i386/kernel/cpu/mcheck/p5.c @@ -28,7 +28,7 @@ static fastcall void pentium_machine_check(struct pt_regs * regs, long error_cod } /* Set up machine check reporting for processors with Intel style MCE */ -void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c) +void intel_p5_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c index 979b18bc95c1..deeae42ce199 100644 --- a/arch/i386/kernel/cpu/mcheck/p6.c +++ b/arch/i386/kernel/cpu/mcheck/p6.c @@ -79,7 +79,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) } /* Set up machine check reporting for processors with Intel style MCE */ -void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c) +void intel_p6_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c index 5b9d2dd411d3..9e424b6c293d 100644 --- a/arch/i386/kernel/cpu/mcheck/winchip.c +++ b/arch/i386/kernel/cpu/mcheck/winchip.c @@ -22,7 +22,7 @@ static fastcall void winchip_machine_check(struct pt_regs * regs, long error_cod } /* Set up machine check reporting on the Winchip C6 series */ -void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c) +void winchip_mcheck_init(struct cpuinfo_x86 *c) { u32 lo, hi; machine_check_vector = winchip_machine_check; diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 1f1572692e0b..50a0bef8c85f 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -118,6 +118,7 @@ void __restore_processor_state(struct saved_context *ctxt) fix_processor_context(); do_fpu_end(); mtrr_ap_init(); + mcheck_init(&boot_cpu_data); } void restore_processor_state(void) diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 0a4ec764377c..8c02b0318703 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -718,4 +718,10 @@ extern void mtrr_bp_init(void); #define mtrr_bp_init() do {} while (0) #endif +#ifdef CONFIG_X86_MCE +extern void mcheck_init(struct cpuinfo_x86 *c); +#else +#define mcheck_init(c) do {} while(0) +#endif + #endif /* __ASM_I386_PROCESSOR_H */ -- cgit v1.2.3 From 5f9c3cbcd5d41be597aef9c0ff64ebfc8a91cd6f Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Mon, 7 Nov 2005 00:58:43 -0800 Subject: [PATCH] cris: printk() duplicate declaration printk() already declared in include/linux/kernel.h so squish the duplication. Besides, no printk() usage here. Bye bye. Signed-off-by: Arthur Othieno Cc: Mikael Starvik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-cris/semaphore.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h index 39faf69bcf76..a19568e6aae6 100644 --- a/include/asm-cris/semaphore.h +++ b/include/asm-cris/semaphore.h @@ -18,8 +18,6 @@ * CRIS semaphores, implemented in C-only so far. */ -int printk(const char *fmt, ...); - struct semaphore { atomic_t count; atomic_t waking; -- cgit v1.2.3 From d9b5444eeb3a663ca4a625878b1421c9e9b18e8b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:58:44 -0800 Subject: [PATCH] cris: "extern inline" -> "static inline" "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Acked-by: Mikael Starvik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/cris/arch-v10/README.mm | 6 ++--- arch/cris/arch-v10/kernel/signal.c | 2 +- arch/cris/arch-v32/kernel/signal.c | 2 +- arch/cris/mm/ioremap.c | 2 +- include/asm-cris/arch-v10/byteorder.h | 4 +-- include/asm-cris/arch-v10/checksum.h | 2 +- include/asm-cris/arch-v10/delay.h | 2 +- include/asm-cris/arch-v10/ide.h | 8 +++--- include/asm-cris/arch-v10/system.h | 8 +++--- include/asm-cris/arch-v10/thread_info.h | 2 +- include/asm-cris/arch-v10/timex.h | 2 +- include/asm-cris/arch-v10/uaccess.h | 4 +-- include/asm-cris/arch-v32/bitops.h | 10 +++---- include/asm-cris/arch-v32/byteorder.h | 4 +-- include/asm-cris/arch-v32/checksum.h | 2 +- include/asm-cris/arch-v32/delay.h | 2 +- include/asm-cris/arch-v32/ide.h | 4 +-- include/asm-cris/arch-v32/io.h | 6 ++--- include/asm-cris/arch-v32/system.h | 6 ++--- include/asm-cris/arch-v32/thread_info.h | 2 +- include/asm-cris/arch-v32/timex.h | 2 +- include/asm-cris/arch-v32/uaccess.h | 4 +-- include/asm-cris/atomic.h | 22 ++++++++-------- include/asm-cris/bitops.h | 18 ++++++------- include/asm-cris/checksum.h | 8 +++--- include/asm-cris/current.h | 2 +- include/asm-cris/delay.h | 2 +- include/asm-cris/io.h | 6 ++--- include/asm-cris/irq.h | 2 +- include/asm-cris/pgalloc.h | 12 ++++----- include/asm-cris/pgtable.h | 46 ++++++++++++++++----------------- include/asm-cris/processor.h | 4 +-- include/asm-cris/semaphore.h | 14 +++++----- include/asm-cris/system.h | 2 +- include/asm-cris/timex.h | 2 +- include/asm-cris/tlbflush.h | 4 +-- include/asm-cris/uaccess.h | 22 ++++++++-------- include/asm-cris/unistd.h | 20 +++++++------- 38 files changed, 136 insertions(+), 136 deletions(-) (limited to 'include') diff --git a/arch/cris/arch-v10/README.mm b/arch/cris/arch-v10/README.mm index 6f08903f3139..517d1f027fe8 100644 --- a/arch/cris/arch-v10/README.mm +++ b/arch/cris/arch-v10/README.mm @@ -177,7 +177,7 @@ The example address is 0xd004000c; in binary this is: Given the top-level Page Directory, the offset in that directory is calculated using the upper 8 bits: -extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) { return mm->pgd + (address >> PGDIR_SHIFT); } @@ -190,14 +190,14 @@ The pgd_t from our example will therefore be the 208'th (0xd0) entry in mm->pgd. Since the Middle Directory does not exist, it is a unity mapping: -extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) { return (pmd_t *) dir; } The Page Table provides the final lookup by using bits 13 to 23 as index: -extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) +static inline pte_t * pte_offset(pmd_t * dir, unsigned long address) { return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 693771961f85..19bcad05716f 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -476,7 +476,7 @@ give_sigsegv: * OK, we're invoking a handler */ -extern inline void +static inline void handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index 0a3614dab887..99e59b3eacf8 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -513,7 +513,7 @@ give_sigsegv: } /* Invoke a singal handler to, well, handle the signal. */ -extern inline void +static inline void handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c index a92ac9877582..1780df3ed9e5 100644 --- a/arch/cris/mm/ioremap.c +++ b/arch/cris/mm/ioremap.c @@ -16,7 +16,7 @@ #include #include -extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, +static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long phys_addr, pgprot_t prot) { unsigned long end; diff --git a/include/asm-cris/arch-v10/byteorder.h b/include/asm-cris/arch-v10/byteorder.h index e24465d1f40d..255b646b7fa8 100644 --- a/include/asm-cris/arch-v10/byteorder.h +++ b/include/asm-cris/arch-v10/byteorder.h @@ -9,14 +9,14 @@ * them together into ntohl etc. */ -extern __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __asm__ ("swapwb %0" : "=r" (x) : "0" (x)); return(x); } -extern __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) { __asm__ ("swapb %0" : "=r" (x) : "0" (x)); diff --git a/include/asm-cris/arch-v10/checksum.h b/include/asm-cris/arch-v10/checksum.h index fde1d00aaa90..633f234f336b 100644 --- a/include/asm-cris/arch-v10/checksum.h +++ b/include/asm-cris/arch-v10/checksum.h @@ -8,7 +8,7 @@ * to split all of those into 16-bit components, then add. */ -extern inline unsigned int +static inline unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) { diff --git a/include/asm-cris/arch-v10/delay.h b/include/asm-cris/arch-v10/delay.h index cfedae0d2f53..39481f6e0c30 100644 --- a/include/asm-cris/arch-v10/delay.h +++ b/include/asm-cris/arch-v10/delay.h @@ -1,7 +1,7 @@ #ifndef _CRIS_ARCH_DELAY_H #define _CRIS_ARCH_DELAY_H -extern __inline__ void __delay(int loops) +static inline void __delay(int loops) { __asm__ __volatile__ ( "move.d %0,$r9\n\t" diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h index 8cf2d7cb22ac..78b301ed7b12 100644 --- a/include/asm-cris/arch-v10/ide.h +++ b/include/asm-cris/arch-v10/ide.h @@ -25,7 +25,7 @@ #define MAX_HWIFS 4 -extern __inline__ int ide_default_irq(unsigned long base) +static inline int ide_default_irq(unsigned long base) { /* all IDE busses share the same IRQ, number 4. * this has the side-effect that ide-probe.c will cluster our 4 interfaces @@ -35,7 +35,7 @@ extern __inline__ int ide_default_irq(unsigned long base) return 4; } -extern __inline__ unsigned long ide_default_io_base(int index) +static inline unsigned long ide_default_io_base(int index) { /* we have no real I/O base address per interface, since all go through the * same register. but in a bitfield in that register, we have the i/f number. @@ -54,7 +54,7 @@ extern __inline__ unsigned long ide_default_io_base(int index) * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us. */ -extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq) +static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq) { int i; @@ -77,7 +77,7 @@ extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_por hw->io_ports[IDE_IRQ_OFFSET] = 0; } -extern __inline__ void ide_init_default_hwifs(void) +static inline void ide_init_default_hwifs(void) { hw_regs_t hw; int index; diff --git a/include/asm-cris/arch-v10/system.h b/include/asm-cris/arch-v10/system.h index 6cc35642b8ab..1ac7b639b1b0 100644 --- a/include/asm-cris/arch-v10/system.h +++ b/include/asm-cris/arch-v10/system.h @@ -5,7 +5,7 @@ /* read the CPU version register */ -extern inline unsigned long rdvr(void) { +static inline unsigned long rdvr(void) { unsigned char vr; __asm__ volatile ("move $vr,%0" : "=rm" (vr)); return vr; @@ -15,7 +15,7 @@ extern inline unsigned long rdvr(void) { /* read/write the user-mode stackpointer */ -extern inline unsigned long rdusp(void) { +static inline unsigned long rdusp(void) { unsigned long usp; __asm__ __volatile__("move $usp,%0" : "=rm" (usp)); return usp; @@ -26,13 +26,13 @@ extern inline unsigned long rdusp(void) { /* read the current stackpointer */ -extern inline unsigned long rdsp(void) { +static inline unsigned long rdsp(void) { unsigned long sp; __asm__ __volatile__("move.d $sp,%0" : "=rm" (sp)); return sp; } -extern inline unsigned long _get_base(char * addr) +static inline unsigned long _get_base(char * addr) { return 0; } diff --git a/include/asm-cris/arch-v10/thread_info.h b/include/asm-cris/arch-v10/thread_info.h index 357f5df0c907..218f4152d3e5 100644 --- a/include/asm-cris/arch-v10/thread_info.h +++ b/include/asm-cris/arch-v10/thread_info.h @@ -2,7 +2,7 @@ #define _ASM_ARCH_THREAD_INFO_H /* how to get the thread information struct from C */ -extern inline struct thread_info *current_thread_info(void) +static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; __asm__("and.d $sp,%0; ":"=r" (ti) : "0" (~8191UL)); diff --git a/include/asm-cris/arch-v10/timex.h b/include/asm-cris/arch-v10/timex.h index ecfc553c06a5..e48447d94faf 100644 --- a/include/asm-cris/arch-v10/timex.h +++ b/include/asm-cris/arch-v10/timex.h @@ -22,7 +22,7 @@ unsigned long get_ns_in_jiffie(void); -extern inline unsigned long get_us_in_jiffie_highres(void) +static inline unsigned long get_us_in_jiffie_highres(void) { return get_ns_in_jiffie()/1000; } diff --git a/include/asm-cris/arch-v10/uaccess.h b/include/asm-cris/arch-v10/uaccess.h index 787d2e60c83c..65b02d9b605a 100644 --- a/include/asm-cris/arch-v10/uaccess.h +++ b/include/asm-cris/arch-v10/uaccess.h @@ -87,7 +87,7 @@ * bytes copied if we hit a null byte * (without the null byte) */ -extern inline long +static inline long __do_strncpy_from_user(char *dst, const char *src, long count) { long res; @@ -602,7 +602,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) * or 0 for error. Return a value greater than N if too long. */ -extern inline long +static inline long strnlen_user(const char *s, long n) { long res, tmp1; diff --git a/include/asm-cris/arch-v32/bitops.h b/include/asm-cris/arch-v32/bitops.h index e40a58d3b862..147689d6b624 100644 --- a/include/asm-cris/arch-v32/bitops.h +++ b/include/asm-cris/arch-v32/bitops.h @@ -8,7 +8,7 @@ * inverts all bits in the input. */ -extern inline unsigned long +static inline unsigned long cris_swapnwbrlz(unsigned long w) { unsigned long res; @@ -20,7 +20,7 @@ cris_swapnwbrlz(unsigned long w) return res; } -extern inline unsigned long +static inline unsigned long cris_swapwbrlz(unsigned long w) { unsigned long res; @@ -36,7 +36,7 @@ cris_swapwbrlz(unsigned long w) * Find First Zero in word. Undefined if no zero exist, so the caller should * check against ~0 first. */ -extern inline unsigned long +static inline unsigned long ffz(unsigned long w) { return cris_swapnwbrlz(w); @@ -46,7 +46,7 @@ ffz(unsigned long w) * Find First Set bit in word. Undefined if no 1 exist, so the caller * should check against 0 first. */ -extern inline unsigned long +static inline unsigned long __ffs(unsigned long w) { return cris_swapnwbrlz(~w); @@ -55,7 +55,7 @@ __ffs(unsigned long w) /* * Find First Bit that is set. */ -extern inline unsigned long +static inline unsigned long kernel_ffs(unsigned long w) { return w ? cris_swapwbrlz (w) + 1 : 0; diff --git a/include/asm-cris/arch-v32/byteorder.h b/include/asm-cris/arch-v32/byteorder.h index 74846ee6cf99..6ef8fb4a35f2 100644 --- a/include/asm-cris/arch-v32/byteorder.h +++ b/include/asm-cris/arch-v32/byteorder.h @@ -3,14 +3,14 @@ #include -extern __inline__ __const__ __u32 +static inline __const__ __u32 ___arch__swab32(__u32 x) { __asm__ __volatile__ ("swapwb %0" : "=r" (x) : "0" (x)); return (x); } -extern __inline__ __const__ __u16 +static inline __const__ __u16 ___arch__swab16(__u16 x) { __asm__ __volatile__ ("swapb %0" : "=r" (x) : "0" (x)); diff --git a/include/asm-cris/arch-v32/checksum.h b/include/asm-cris/arch-v32/checksum.h index a1d6b2a6cc44..97ef89efea62 100644 --- a/include/asm-cris/arch-v32/checksum.h +++ b/include/asm-cris/arch-v32/checksum.h @@ -9,7 +9,7 @@ * checksum. Which means it would be necessary to split all those into * 16-bit components and then add. */ -extern inline unsigned int +static inline unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) { diff --git a/include/asm-cris/arch-v32/delay.h b/include/asm-cris/arch-v32/delay.h index f36f7f760e89..b6e941e637de 100644 --- a/include/asm-cris/arch-v32/delay.h +++ b/include/asm-cris/arch-v32/delay.h @@ -1,7 +1,7 @@ #ifndef _ASM_CRIS_ARCH_DELAY_H #define _ASM_CRIS_ARCH_DELAY_H -extern __inline__ void +static inline void __delay(int loops) { __asm__ __volatile__ ( diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h index 24f5604f566a..6590f657500d 100644 --- a/include/asm-cris/arch-v32/ide.h +++ b/include/asm-cris/arch-v32/ide.h @@ -26,7 +26,7 @@ #define MAX_HWIFS 4 -extern __inline__ int ide_default_irq(unsigned long base) +static inline int ide_default_irq(unsigned long base) { /* all IDE busses share the same IRQ, * this has the side-effect that ide-probe.c will cluster our 4 interfaces @@ -36,7 +36,7 @@ extern __inline__ int ide_default_irq(unsigned long base) return ATA_INTR_VECT; } -extern __inline__ unsigned long ide_default_io_base(int index) +static inline unsigned long ide_default_io_base(int index) { reg_ata_rw_ctrl2 ctrl2 = {.sel = index}; /* we have no real I/O base address per interface, since all go through the diff --git a/include/asm-cris/arch-v32/io.h b/include/asm-cris/arch-v32/io.h index 4c80263ec634..043c9ce5294e 100644 --- a/include/asm-cris/arch-v32/io.h +++ b/include/asm-cris/arch-v32/io.h @@ -35,7 +35,7 @@ extern struct crisv32_iopin crisv32_led2_red; extern struct crisv32_iopin crisv32_led3_green; extern struct crisv32_iopin crisv32_led3_red; -extern inline void crisv32_io_set(struct crisv32_iopin* iopin, +static inline void crisv32_io_set(struct crisv32_iopin* iopin, int val) { if (val) @@ -44,7 +44,7 @@ extern inline void crisv32_io_set(struct crisv32_iopin* iopin, *iopin->port->data &= ~iopin->bit; } -extern inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, +static inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, enum crisv32_io_dir dir) { if (dir == crisv32_io_dir_in) @@ -53,7 +53,7 @@ extern inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, *iopin->port->oe |= iopin->bit; } -extern inline int crisv32_io_rd(struct crisv32_iopin* iopin) +static inline int crisv32_io_rd(struct crisv32_iopin* iopin) { return ((*iopin->port->data_in & iopin->bit) ? 1 : 0); } diff --git a/include/asm-cris/arch-v32/system.h b/include/asm-cris/arch-v32/system.h index b9afbb95e0bb..a3d75d581e2f 100644 --- a/include/asm-cris/arch-v32/system.h +++ b/include/asm-cris/arch-v32/system.h @@ -4,7 +4,7 @@ #include /* Read the CPU version register. */ -extern inline unsigned long rdvr(void) +static inline unsigned long rdvr(void) { unsigned char vr; @@ -15,7 +15,7 @@ extern inline unsigned long rdvr(void) #define cris_machine_name "crisv32" /* Read the user-mode stack pointer. */ -extern inline unsigned long rdusp(void) +static inline unsigned long rdusp(void) { unsigned long usp; @@ -24,7 +24,7 @@ extern inline unsigned long rdusp(void) } /* Read the current stack pointer. */ -extern inline unsigned long rdsp(void) +static inline unsigned long rdsp(void) { unsigned long sp; diff --git a/include/asm-cris/arch-v32/thread_info.h b/include/asm-cris/arch-v32/thread_info.h index a7a182307da0..d6936956a3c6 100644 --- a/include/asm-cris/arch-v32/thread_info.h +++ b/include/asm-cris/arch-v32/thread_info.h @@ -2,7 +2,7 @@ #define _ASM_CRIS_ARCH_THREAD_INFO_H /* Return a thread_info struct. */ -extern inline struct thread_info *current_thread_info(void) +static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; diff --git a/include/asm-cris/arch-v32/timex.h b/include/asm-cris/arch-v32/timex.h index 4d0fd23b21e9..5a4aa285d5fd 100644 --- a/include/asm-cris/arch-v32/timex.h +++ b/include/asm-cris/arch-v32/timex.h @@ -22,7 +22,7 @@ extern unsigned long get_ns_in_jiffie(void); -extern inline unsigned long get_us_in_jiffie_highres(void) +static inline unsigned long get_us_in_jiffie_highres(void) { return get_ns_in_jiffie() / 1000; } diff --git a/include/asm-cris/arch-v32/uaccess.h b/include/asm-cris/arch-v32/uaccess.h index 055a0bdbe835..6b207f1b6622 100644 --- a/include/asm-cris/arch-v32/uaccess.h +++ b/include/asm-cris/arch-v32/uaccess.h @@ -93,7 +93,7 @@ * bytes copied if we hit a null byte * (without the null byte) */ -extern inline long +static inline long __do_strncpy_from_user(char *dst, const char *src, long count) { long res; @@ -695,7 +695,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) * or 0 for error. Return a value greater than N if too long. */ -extern inline long +static inline long strnlen_user(const char *s, long n) { long res, tmp1; diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h index 70605b09e8b7..8c2e78304523 100644 --- a/include/asm-cris/atomic.h +++ b/include/asm-cris/atomic.h @@ -20,7 +20,7 @@ typedef struct { volatile int counter; } atomic_t; /* These should be written in asm but we do it in C for now. */ -extern __inline__ void atomic_add(int i, volatile atomic_t *v) +static inline void atomic_add(int i, volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -28,7 +28,7 @@ extern __inline__ void atomic_add(int i, volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ void atomic_sub(int i, volatile atomic_t *v) +static inline void atomic_sub(int i, volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -36,7 +36,7 @@ extern __inline__ void atomic_sub(int i, volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ int atomic_add_return(int i, volatile atomic_t *v) +static inline int atomic_add_return(int i, volatile atomic_t *v) { unsigned long flags; int retval; @@ -48,7 +48,7 @@ extern __inline__ int atomic_add_return(int i, volatile atomic_t *v) #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) -extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v) +static inline int atomic_sub_return(int i, volatile atomic_t *v) { unsigned long flags; int retval; @@ -58,7 +58,7 @@ extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v) return retval; } -extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v) +static inline int atomic_sub_and_test(int i, volatile atomic_t *v) { int retval; unsigned long flags; @@ -68,7 +68,7 @@ extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v) return retval; } -extern __inline__ void atomic_inc(volatile atomic_t *v) +static inline void atomic_inc(volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -76,7 +76,7 @@ extern __inline__ void atomic_inc(volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ void atomic_dec(volatile atomic_t *v) +static inline void atomic_dec(volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -84,7 +84,7 @@ extern __inline__ void atomic_dec(volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ int atomic_inc_return(volatile atomic_t *v) +static inline int atomic_inc_return(volatile atomic_t *v) { unsigned long flags; int retval; @@ -94,7 +94,7 @@ extern __inline__ int atomic_inc_return(volatile atomic_t *v) return retval; } -extern __inline__ int atomic_dec_return(volatile atomic_t *v) +static inline int atomic_dec_return(volatile atomic_t *v) { unsigned long flags; int retval; @@ -103,7 +103,7 @@ extern __inline__ int atomic_dec_return(volatile atomic_t *v) cris_atomic_restore(v, flags); return retval; } -extern __inline__ int atomic_dec_and_test(volatile atomic_t *v) +static inline int atomic_dec_and_test(volatile atomic_t *v) { int retval; unsigned long flags; @@ -113,7 +113,7 @@ extern __inline__ int atomic_dec_and_test(volatile atomic_t *v) return retval; } -extern __inline__ int atomic_inc_and_test(volatile atomic_t *v) +static inline int atomic_inc_and_test(volatile atomic_t *v) { int retval; unsigned long flags; diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h index e3da57f97964..1bddb3f3a289 100644 --- a/include/asm-cris/bitops.h +++ b/include/asm-cris/bitops.h @@ -89,7 +89,7 @@ struct __dummy { unsigned long a[100]; }; * It also implies a memory barrier. */ -extern inline int test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int test_and_set_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned long flags; @@ -105,7 +105,7 @@ extern inline int test_and_set_bit(int nr, volatile unsigned long *addr) return retval; } -extern inline int __test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned int *adr = (unsigned int *)addr; @@ -132,7 +132,7 @@ extern inline int __test_and_set_bit(int nr, volatile unsigned long *addr) * It also implies a memory barrier. */ -extern inline int test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned long flags; @@ -157,7 +157,7 @@ extern inline int test_and_clear_bit(int nr, volatile unsigned long *addr) * but actually fail. You must protect multiple accesses with a lock. */ -extern inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned int *adr = (unsigned int *)addr; @@ -177,7 +177,7 @@ extern inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) * It also implies a memory barrier. */ -extern inline int test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int test_and_change_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned long flags; @@ -193,7 +193,7 @@ extern inline int test_and_change_bit(int nr, volatile unsigned long *addr) /* WARNING: non atomic and it can be reordered! */ -extern inline int __test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_change_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned int *adr = (unsigned int *)addr; @@ -214,7 +214,7 @@ extern inline int __test_and_change_bit(int nr, volatile unsigned long *addr) * This routine doesn't need to be atomic. */ -extern inline int test_bit(int nr, const volatile unsigned long *addr) +static inline int test_bit(int nr, const volatile unsigned long *addr) { unsigned int mask; unsigned int *adr = (unsigned int *)addr; @@ -258,7 +258,7 @@ extern inline int test_bit(int nr, const volatile unsigned long *addr) * @offset: The bitnumber to start searching at * @size: The maximum size to search */ -extern inline int find_next_zero_bit (const unsigned long * addr, int size, int offset) +static inline int find_next_zero_bit (const unsigned long * addr, int size, int offset) { unsigned long *p = ((unsigned long *) addr) + (offset >> 5); unsigned long result = offset & ~31UL; @@ -366,7 +366,7 @@ found_middle: #define minix_test_bit(nr,addr) test_bit(nr,addr) #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) -extern inline int sched_find_first_bit(const unsigned long *b) +static inline int sched_find_first_bit(const unsigned long *b) { if (unlikely(b[0])) return __ffs(b[0]); diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h index 15ca8aec5c63..26a7719bbb84 100644 --- a/include/asm-cris/checksum.h +++ b/include/asm-cris/checksum.h @@ -34,7 +34,7 @@ unsigned int csum_partial_copy_nocheck(const char *src, char *dst, * Fold a partial checksum into a word */ -extern inline unsigned int csum_fold(unsigned int sum) +static inline unsigned int csum_fold(unsigned int sum) { /* the while loop is unnecessary really, it's always enough with two iterations */ @@ -55,7 +55,7 @@ extern unsigned int csum_partial_copy_from_user(const char *src, char *dst, * */ -extern inline unsigned short ip_fast_csum(unsigned char * iph, +static inline unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { return csum_fold(csum_partial(iph, ihl * 4, 0)); @@ -66,7 +66,7 @@ extern inline unsigned short ip_fast_csum(unsigned char * iph, * returns a 16-bit checksum, already complemented */ -extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr, +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, @@ -80,7 +80,7 @@ extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr, * in icmp.c */ -extern inline unsigned short ip_compute_csum(unsigned char * buff, int len) { +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) { return csum_fold (csum_partial(buff, len, 0)); } diff --git a/include/asm-cris/current.h b/include/asm-cris/current.h index dce69c99da39..5f5c0efd00be 100644 --- a/include/asm-cris/current.h +++ b/include/asm-cris/current.h @@ -5,7 +5,7 @@ struct task_struct; -extern inline struct task_struct * get_current(void) +static inline struct task_struct * get_current(void) { return current_thread_info()->task; } diff --git a/include/asm-cris/delay.h b/include/asm-cris/delay.h index efc41aad4845..d3a397803719 100644 --- a/include/asm-cris/delay.h +++ b/include/asm-cris/delay.h @@ -13,7 +13,7 @@ extern unsigned long loops_per_usec; /* arch/cris/mm/init.c */ -extern __inline__ void udelay(unsigned long usecs) +static inline void udelay(unsigned long usecs) { __delay(usecs * loops_per_usec); } diff --git a/include/asm-cris/io.h b/include/asm-cris/io.h index 16e791b3c721..716c69bc58f8 100644 --- a/include/asm-cris/io.h +++ b/include/asm-cris/io.h @@ -23,12 +23,12 @@ extern struct cris_io_operations *cris_iops; * Change virtual addresses to physical addresses and vv. */ -extern inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile void * address) { return __pa(address); } -extern inline void * phys_to_virt(unsigned long address) +static inline void * phys_to_virt(unsigned long address) { return __va(address); } @@ -36,7 +36,7 @@ extern inline void * phys_to_virt(unsigned long address) extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); extern void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot); -extern inline void __iomem * ioremap (unsigned long offset, unsigned long size) +static inline void __iomem * ioremap (unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } diff --git a/include/asm-cris/irq.h b/include/asm-cris/irq.h index 4fab5c3b2e15..4b338792218b 100644 --- a/include/asm-cris/irq.h +++ b/include/asm-cris/irq.h @@ -8,7 +8,7 @@ #include -extern __inline__ int irq_canonicalize(int irq) +static inline int irq_canonicalize(int irq) { return irq; } diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h index a131776edf41..deaddfe79bbc 100644 --- a/include/asm-cris/pgalloc.h +++ b/include/asm-cris/pgalloc.h @@ -11,35 +11,35 @@ * Allocate and free page tables. */ -extern inline pgd_t *pgd_alloc (struct mm_struct *mm) +static inline pgd_t *pgd_alloc (struct mm_struct *mm) { return (pgd_t *)get_zeroed_page(GFP_KERNEL); } -extern inline void pgd_free (pgd_t *pgd) +static inline void pgd_free (pgd_t *pgd) { free_page((unsigned long)pgd); } -extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } -extern inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *pte; pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); return pte; } -extern inline void pte_free_kernel(pte_t *pte) +static inline void pte_free_kernel(pte_t *pte) { free_page((unsigned long)pte); } -extern inline void pte_free(struct page *pte) +static inline void pte_free(struct page *pte) { __free_page(pte); } diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h index a9143bed99db..70a832514f62 100644 --- a/include/asm-cris/pgtable.h +++ b/include/asm-cris/pgtable.h @@ -112,44 +112,44 @@ extern unsigned long empty_zero_page; * Undefined behaviour if not.. */ -extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; } -extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } -extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; } -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } - -extern inline pte_t pte_wrprotect(pte_t pte) +static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; } +static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } +static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; } +static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } +static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } + +static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); return pte; } -extern inline pte_t pte_rdprotect(pte_t pte) +static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte; } -extern inline pte_t pte_exprotect(pte_t pte) +static inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte; } -extern inline pte_t pte_mkclean(pte_t pte) +static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); return pte; } -extern inline pte_t pte_mkold(pte_t pte) +static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) +static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; if (pte_val(pte) & _PAGE_MODIFIED) @@ -157,7 +157,7 @@ extern inline pte_t pte_mkwrite(pte_t pte) return pte; } -extern inline pte_t pte_mkread(pte_t pte) +static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; if (pte_val(pte) & _PAGE_ACCESSED) @@ -165,7 +165,7 @@ extern inline pte_t pte_mkread(pte_t pte) return pte; } -extern inline pte_t pte_mkexec(pte_t pte) +static inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_READ; if (pte_val(pte) & _PAGE_ACCESSED) @@ -173,7 +173,7 @@ extern inline pte_t pte_mkexec(pte_t pte) return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) +static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_MODIFIED; if (pte_val(pte) & _PAGE_WRITE) @@ -181,7 +181,7 @@ extern inline pte_t pte_mkdirty(pte_t pte) return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) +static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; if (pte_val(pte) & _PAGE_READ) @@ -205,7 +205,7 @@ extern inline pte_t pte_mkyoung(pte_t pte) * addresses (the 0xc0xxxxxx's) goes as void *'s. */ -extern inline pte_t __mk_pte(void * page, pgprot_t pgprot) +static inline pte_t __mk_pte(void * page, pgprot_t pgprot) { pte_t pte; /* the PTE needs a physical address */ @@ -223,7 +223,7 @@ extern inline pte_t __mk_pte(void * page, pgprot_t pgprot) __pte; \ }) -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } @@ -232,7 +232,7 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * pte_pagenr refers to the page-number counted starting from the virtual DRAM start */ -extern inline unsigned long __pte_page(pte_t pte) +static inline unsigned long __pte_page(pte_t pte) { /* the PTE contains a physical address */ return (unsigned long)__va(pte_val(pte) & PAGE_MASK); @@ -250,7 +250,7 @@ extern inline unsigned long __pte_page(pte_t pte) * don't need the __pa and __va transformations. */ -extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) +static inline void pmd_set(pmd_t * pmdp, pte_t * ptep) { pmd_val(*pmdp) = _PAGE_TABLE | (unsigned long) ptep; } #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) @@ -260,7 +260,7 @@ extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) /* to find an entry in a page-table-directory */ -extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) { return mm->pgd + pgd_index(address); } @@ -296,7 +296,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ * * Actually I am not sure on what this could be used for. */ -extern inline void update_mmu_cache(struct vm_area_struct * vma, +static inline void update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) { } diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h index 0dc218117bd8..e8b2abb2ae59 100644 --- a/include/asm-cris/processor.h +++ b/include/asm-cris/processor.h @@ -45,7 +45,7 @@ #define current_regs() user_regs(current->thread_info) -extern inline void prepare_to_copy(struct task_struct *tsk) +static inline void prepare_to_copy(struct task_struct *tsk) { } @@ -58,7 +58,7 @@ unsigned long get_wchan(struct task_struct *p); extern unsigned long thread_saved_pc(struct task_struct *tsk); /* Free all resources held by a thread. */ -extern inline void release_thread(struct task_struct *dead_task) +static inline void release_thread(struct task_struct *dead_task) { /* Nothing needs to be done. */ } diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h index a19568e6aae6..53f548b791c1 100644 --- a/include/asm-cris/semaphore.h +++ b/include/asm-cris/semaphore.h @@ -37,17 +37,17 @@ struct semaphore { #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) -extern inline void sema_init(struct semaphore *sem, int val) +static inline void sema_init(struct semaphore *sem, int val) { *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); } -extern inline void init_MUTEX (struct semaphore *sem) +static inline void init_MUTEX (struct semaphore *sem) { sema_init(sem, 1); } -extern inline void init_MUTEX_LOCKED (struct semaphore *sem) +static inline void init_MUTEX_LOCKED (struct semaphore *sem) { sema_init(sem, 0); } @@ -59,7 +59,7 @@ extern void __up(struct semaphore * sem); /* notice - we probably can do cli/sti here instead of saving */ -extern inline void down(struct semaphore * sem) +static inline void down(struct semaphore * sem) { unsigned long flags; int failed; @@ -81,7 +81,7 @@ extern inline void down(struct semaphore * sem) * returns negative for signalled and zero for semaphore acquired. */ -extern inline int down_interruptible(struct semaphore * sem) +static inline int down_interruptible(struct semaphore * sem) { unsigned long flags; int failed; @@ -97,7 +97,7 @@ extern inline int down_interruptible(struct semaphore * sem) return(failed); } -extern inline int down_trylock(struct semaphore * sem) +static inline int down_trylock(struct semaphore * sem) { unsigned long flags; int failed; @@ -117,7 +117,7 @@ extern inline int down_trylock(struct semaphore * sem) * The default case (no contention) will result in NO * jumps for both down() and up(). */ -extern inline void up(struct semaphore * sem) +static inline void up(struct semaphore * sem) { unsigned long flags; int wakeup; diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h index e06739806d4e..d48670107a85 100644 --- a/include/asm-cris/system.h +++ b/include/asm-cris/system.h @@ -41,7 +41,7 @@ extern struct task_struct *resume(struct task_struct *prev, struct task_struct * void disable_hlt(void); void enable_hlt(void); -extern inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { /* since Etrax doesn't have any atomic xchg instructions, we need to disable irq's (if enabled) and do it with move.d's */ diff --git a/include/asm-cris/timex.h b/include/asm-cris/timex.h index 3fb069a37717..b92e0e80fe86 100644 --- a/include/asm-cris/timex.h +++ b/include/asm-cris/timex.h @@ -16,7 +16,7 @@ typedef unsigned long long cycles_t; -extern inline cycles_t get_cycles(void) +static inline cycles_t get_cycles(void) { return 0; } diff --git a/include/asm-cris/tlbflush.h b/include/asm-cris/tlbflush.h index 6ed7d9ae90db..c52238005b55 100644 --- a/include/asm-cris/tlbflush.h +++ b/include/asm-cris/tlbflush.h @@ -39,14 +39,14 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st flush_tlb_mm(vma->vm_mm); } -extern inline void flush_tlb_pgtables(struct mm_struct *mm, +static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) { /* CRIS does not keep any page table caches in TLB */ } -extern inline void flush_tlb(void) +static inline void flush_tlb(void) { flush_tlb_mm(current->mm); } diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h index 7d50086eb5ea..69d48a2dc8e1 100644 --- a/include/asm-cris/uaccess.h +++ b/include/asm-cris/uaccess.h @@ -213,7 +213,7 @@ extern unsigned long __copy_user(void *to, const void *from, unsigned long n); extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n); extern unsigned long __do_clear_user(void *to, unsigned long n); -extern inline unsigned long +static inline unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) @@ -221,7 +221,7 @@ __generic_copy_to_user(void __user *to, const void *from, unsigned long n) return n; } -extern inline unsigned long +static inline unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) @@ -229,7 +229,7 @@ __generic_copy_from_user(void *to, const void __user *from, unsigned long n) return n; } -extern inline unsigned long +static inline unsigned long __generic_clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) @@ -237,13 +237,13 @@ __generic_clear_user(void __user *to, unsigned long n) return n; } -extern inline long +static inline long __strncpy_from_user(char *dst, const char __user *src, long count) { return __do_strncpy_from_user(dst, src, count); } -extern inline long +static inline long strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; @@ -256,7 +256,7 @@ strncpy_from_user(char *dst, const char __user *src, long count) /* Note that if these expand awfully if made into switch constructs, so don't do that. */ -extern inline unsigned long +static inline unsigned long __constant_copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long ret = 0; @@ -306,7 +306,7 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n) /* Ditto, don't make a switch out of this. */ -extern inline unsigned long +static inline unsigned long __constant_copy_to_user(void __user *to, const void *from, unsigned long n) { unsigned long ret = 0; @@ -356,7 +356,7 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) /* No switch, please. */ -extern inline unsigned long +static inline unsigned long __constant_clear_user(void __user *to, unsigned long n) { unsigned long ret = 0; @@ -406,19 +406,19 @@ __constant_clear_user(void __user *to, unsigned long n) * used in fast paths and have only a small space overhead. */ -extern inline unsigned long +static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { return __copy_user_zeroing(to,from,n); } -extern inline unsigned long +static inline unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) { return __copy_user(to,from,n); } -extern inline unsigned long +static inline unsigned long __generic_clear_user_nocheck(void *to, unsigned long n) { return __do_clear_user(to,n); diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h index 156a34bfc583..2627bbdf8a11 100644 --- a/include/asm-cris/unistd.h +++ b/include/asm-cris/unistd.h @@ -343,14 +343,14 @@ * some others too. */ #define __NR__exit __NR_exit -extern inline _syscall0(pid_t,setsid) -extern inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) -extern inline _syscall3(int,read,int,fd,char *,buf,off_t,count) -extern inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) -extern inline _syscall1(int,dup,int,fd) -extern inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) -extern inline _syscall3(int,open,const char *,file,int,flag,int,mode) -extern inline _syscall1(int,close,int,fd) +static inline _syscall0(pid_t,setsid) +static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) +static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) +static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) +static inline _syscall1(int,dup,int,fd) +static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) +static inline _syscall3(int,open,const char *,file,int,flag,int,mode) +static inline _syscall1(int,close,int,fd) struct pt_regs; asmlinkage long sys_mmap2( @@ -382,8 +382,8 @@ asmlinkage long sys_rt_sigaction(int sig, #ifdef __KERNEL__ #define _exit kernel_syscall_exit #endif -extern inline _syscall1(int,_exit,int,exitcode) -extern inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) +static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) #endif -- cgit v1.2.3 From e763b793f7e5c09a859fc420eb0de385d80cf636 Mon Sep 17 00:00:00 2001 From: Ben Lahaise Date: Mon, 7 Nov 2005 00:58:52 -0800 Subject: [PATCH] uml: switch_mm fix Not quite, something along the lines of the patch below works correctly (and makes aio performance not suffer from multiple second delays), as skas0 mode correctly switches mm contexts, unlike TT (which should probably get nuked from the kernel now that skas0 seems to be working). Signed-off-by: Benjamin LaHaise Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/mmu_context.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h index 2edb4f1f789c..9a0e48eb542e 100644 --- a/include/asm-um/mmu_context.h +++ b/include/asm-um/mmu_context.h @@ -29,7 +29,8 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) * possible. */ if (old != new && (current->flags & PF_BORROWED_MM)) - force_flush_all(); + CHOOSE_MODE(force_flush_all(), + switch_mm_skas(&new->context.skas.id)); } static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, -- cgit v1.2.3 From 858259cf7d1c443c836a2022b78cb281f0a9b95e Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Mon, 7 Nov 2005 00:58:55 -0800 Subject: [PATCH] uml: maintain own LDT entries Patch imlements full LDT handling in SKAS: * UML holds it's own LDT table, used to deliver data on modify_ldt(READ) * UML disables the default_ldt, inherited from the host (SKAS3) or resets LDT entries, set by host's clib and inherited in SKAS0 * A new global variable skas_needs_stub is inserted, that can be used to decide, whether stub-pages must be supported or not. * Uses the syscall-stub to replace missing PTRACE_LDT (therefore, write_ldt_entry needs to be modified) Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/include/mmu-skas.h | 2 + arch/um/kernel/skas/include/skas.h | 3 +- arch/um/kernel/skas/mem.c | 2 +- arch/um/kernel/skas/mmu.c | 44 +-- arch/um/kernel/skas/process.c | 6 +- arch/um/kernel/skas/process_kern.c | 2 +- arch/um/os-Linux/start_up.c | 75 ++++- arch/um/scripts/Makefile.rules | 7 +- arch/um/sys-i386/ldt.c | 506 ++++++++++++++++++++++++++++++--- arch/um/sys-x86_64/Makefile | 5 +- arch/um/sys-x86_64/syscalls.c | 75 ----- include/asm-um/ldt-i386.h | 69 +++++ include/asm-um/ldt.h | 69 +++++ 13 files changed, 724 insertions(+), 141 deletions(-) create mode 100644 include/asm-um/ldt-i386.h (limited to 'include') diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h index 09536f81ee42..44110c521e49 100644 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ b/arch/um/kernel/skas/include/mmu-skas.h @@ -8,6 +8,7 @@ #include "linux/config.h" #include "mm_id.h" +#include "asm/ldt.h" struct mmu_context_skas { struct mm_id id; @@ -15,6 +16,7 @@ struct mmu_context_skas { #ifdef CONFIG_3_LEVEL_PGTABLES unsigned long last_pmd; #endif + uml_ldt_t ldt; }; extern void switch_mm_skas(struct mm_id * mm_idp); diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index 060934740f9f..daa2f85b684c 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -10,7 +10,8 @@ #include "sysdep/ptrace.h" extern int userspace_pid[]; -extern int proc_mm, ptrace_faultinfo; +extern int proc_mm, ptrace_faultinfo, ptrace_ldt; +extern int skas_needs_stub; extern void switch_threads(void *me, void *next); extern void thread_wait(void *sw, void *fb); diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 147466d7ff4f..88ab96c609ce 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, *task_size_out = CONFIG_HOST_TASK_SIZE; #else *host_size_out = top; - if (proc_mm && ptrace_faultinfo) + if (!skas_needs_stub) *task_size_out = top; else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; #endif diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 9e5e39cea821..677871f1b37c 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -15,6 +15,7 @@ #include "asm/mmu.h" #include "asm/pgalloc.h" #include "asm/pgtable.h" +#include "asm/ldt.h" #include "os.h" #include "skas.h" @@ -74,13 +75,12 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) { - struct mm_struct *cur_mm = current->mm; - struct mm_id *cur_mm_id = &cur_mm->context.skas.id; - struct mm_id *mm_id = &mm->context.skas.id; + struct mmu_context_skas *from_mm = NULL; + struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; - int from, ret = -ENOMEM; + int from_fd, ret = -ENOMEM; - if(!proc_mm || !ptrace_faultinfo){ + if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); if(stack == 0) goto out; @@ -102,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) mm->nr_ptes--; } - mm_id->stack = stack; + + to_mm->id.stack = stack; + if(current->mm != NULL && current->mm != &init_mm) + from_mm = ¤t->mm->context.skas; if(proc_mm){ - if((cur_mm != NULL) && (cur_mm != &init_mm)) - from = cur_mm_id->u.mm_fd; - else from = -1; + if(from_mm) + from_fd = from_mm->id.u.mm_fd; + else from_fd = -1; - ret = new_mm(from, stack); + ret = new_mm(from_fd, stack); if(ret < 0){ printk("init_new_context_skas - new_mm failed, " "errno = %d\n", ret); goto out_free; } - mm_id->u.mm_fd = ret; + to_mm->id.u.mm_fd = ret; } else { - if((cur_mm != NULL) && (cur_mm != &init_mm)) - mm_id->u.pid = copy_context_skas0(stack, - cur_mm_id->u.pid); - else mm_id->u.pid = start_userspace(stack); + if(from_mm) + to_mm->id.u.pid = copy_context_skas0(stack, + from_mm->id.u.pid); + else to_mm->id.u.pid = start_userspace(stack); + } + + ret = init_new_ldt(to_mm, from_mm); + if(ret < 0){ + printk("init_new_context_skas - init_ldt" + " failed, errno = %d\n", ret); + goto out_free; } return 0; out_free: - if(mm_id->stack != 0) - free_page(mm_id->stack); + if(to_mm->id.stack != 0) + free_page(to_mm->id.stack); out: return ret; } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 42f2da687dc8..599d679bd4fc 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -381,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid) } /* - * This is used only, if proc_mm is available, while PTRACE_FAULTINFO - * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages - * Thus, we map them using /proc/mm-fd + * This is used only, if stub pages are needed, while proc_mm is + * availabl. Opening /proc/mm creates a new mm_context, which lacks + * the stub-pages. Thus, we map them using /proc/mm-fd */ void map_stub_pages(int fd, unsigned long code, unsigned long data, unsigned long stack) diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index efe92e8aa2a9..9c990253966c 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack) "err = %d\n", -n); } - if(!ptrace_faultinfo) + if(skas_needs_stub) map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); return(fd); diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b99ab414542f..553a09c7d0bc 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -135,7 +135,9 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, } int ptrace_faultinfo = 1; +int ptrace_ldt = 1; int proc_mm = 1; +int skas_needs_stub = 0; static int __init skas0_cmd_param(char *str, int* add) { @@ -352,14 +354,26 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, " it. To support PTRACE_FAULTINFO, the host needs to be patched\n" " using the current skas3 patch.\n\n"); +static int __init noptraceldt_cmd_param(char *str, int* add) +{ + ptrace_ldt = 0; + return 0; +} + +__uml_setup("noptraceldt", noptraceldt_cmd_param, +"noptraceldt\n" +" Turns off usage of PTRACE_LDT, even if host supports it.\n" +" To support PTRACE_LDT, the host needs to be patched using\n" +" the current skas3 patch.\n\n"); + #ifdef UML_CONFIG_MODE_SKAS -static inline void check_skas3_ptrace_support(void) +static inline void check_skas3_ptrace_faultinfo(void) { struct ptrace_faultinfo fi; void *stack; int pid, n; - printf("Checking for the skas3 patch in the host..."); + printf(" - PTRACE_FAULTINFO..."); pid = start_ptraced_child(&stack); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); @@ -381,9 +395,49 @@ static inline void check_skas3_ptrace_support(void) stop_ptraced_child(pid, stack, 1, 1); } -int can_do_skas(void) +static inline void check_skas3_ptrace_ldt(void) +{ +#ifdef PTRACE_LDT + void *stack; + int pid, n; + unsigned char ldtbuf[40]; + struct ptrace_ldt ldt_op = (struct ptrace_ldt) { + .func = 2, /* read default ldt */ + .ptr = ldtbuf, + .bytecount = sizeof(ldtbuf)}; + + printf(" - PTRACE_LDT..."); + pid = start_ptraced_child(&stack); + + n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); + if (n < 0) { + if(errno == EIO) + printf("not found\n"); + else { + perror("not found"); + } + ptrace_ldt = 0; + } + else { + if(ptrace_ldt) + printf("found\n"); + else + printf("found, but use is disabled\n"); + } + + stop_ptraced_child(pid, stack, 1, 1); +#else + /* PTRACE_LDT might be disabled via cmdline option. + * We want to override this, else we might use the stub + * without real need + */ + ptrace_ldt = 1; +#endif +} + +static inline void check_skas3_proc_mm(void) { - printf("Checking for /proc/mm..."); + printf(" - /proc/mm..."); if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { proc_mm = 0; printf("not found\n"); @@ -394,8 +448,19 @@ int can_do_skas(void) else printf("found\n"); } +} + +int can_do_skas(void) +{ + printf("Checking for the skas3 patch in the host:\n"); + + check_skas3_proc_mm(); + check_skas3_ptrace_faultinfo(); + check_skas3_ptrace_ldt(); + + if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt) + skas_needs_stub = 1; - check_skas3_ptrace_support(); return 1; } #else diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index 651d9d88b656..b3fbf125709b 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -26,8 +26,13 @@ define unprofile $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) endef +# cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If +# so, it's considered to be a path relative to $(srcdir) rather than +# $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from +# arch/um/sys-i386 rather than arch/i386 like the other borrowed files. So, +# it sets $(ldt.c-dir) to /arch/um/sys-i386. quiet_cmd_make_link = SYMLINK $@ -cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@ +cmd_make_link = rm -f $@; ln -sf $(srctree)$(if $(filter-out /%,$($(notdir $@)-dir)),/arch/$(SUBARCH))/$($(notdir $@)-dir)/$(notdir $@) $@ # this needs to be before the foreach, because targets does not accept # complete paths like $(obj)/$(f). To make sure this works, use a := assignment diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 36b5c2c13289..6360f1c958d0 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -3,53 +3,26 @@ * Licensed under the GPL */ +#include "linux/stddef.h" #include "linux/config.h" #include "linux/sched.h" #include "linux/slab.h" #include "linux/types.h" +#include "linux/errno.h" #include "asm/uaccess.h" -#include "asm/ptrace.h" #include "asm/smp.h" #include "asm/ldt.h" +#include "asm/unistd.h" #include "choose-mode.h" #include "kern.h" #include "mode_kern.h" -#ifdef CONFIG_MODE_TT - extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -static int do_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -{ - return modify_ldt(func, ptr, bytecount); -} - -#endif - -#ifdef CONFIG_MODE_SKAS - -#include "skas.h" -#include "skas_ptrace.h" - -static int do_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -{ - struct ptrace_ldt ldt; - u32 cpu; - int res; - - ldt = ((struct ptrace_ldt) { .func = func, - .ptr = ptr, - .bytecount = bytecount }); - - cpu = get_cpu(); - res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, (unsigned long) &ldt); - put_cpu(); - - return res; -} -#endif +#ifdef CONFIG_MODE_TT -int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +static long do_modify_ldt_tt(int func, void __user *ptr, + unsigned long bytecount) { struct user_desc info; int res = 0; @@ -89,8 +62,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) goto out; } - res = CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, - p, bytecount); + res = modify_ldt(func, p, bytecount); if(res < 0) goto out; @@ -108,3 +80,467 @@ out: kfree(buf); return res; } + +#endif + +#ifdef CONFIG_MODE_SKAS + +#include "skas.h" +#include "skas_ptrace.h" +#include "asm/mmu_context.h" + +long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, + void **addr, int done) +{ + long res; + + if(proc_mm){ + /* This is a special handling for the case, that the mm to + * modify isn't current->active_mm. + * If this is called directly by modify_ldt, + * (current->active_mm->context.skas.u == mm_idp) + * will be true. So no call to switch_mm_skas(mm_idp) is done. + * If this is called in case of init_new_ldt or PTRACE_LDT, + * mm_idp won't belong to current->active_mm, but child->mm. + * So we need to switch child's mm into our userspace, then + * later switch back. + * + * Note: I'm unshure: should interrupts be disabled here? + */ + if(!current->active_mm || current->active_mm == &init_mm || + mm_idp != ¤t->active_mm->context.skas.id) + switch_mm_skas(mm_idp); + } + + if(ptrace_ldt) { + struct ptrace_ldt ldt_op = (struct ptrace_ldt) { + .func = func, + .ptr = desc, + .bytecount = sizeof(*desc)}; + u32 cpu; + int pid; + + if(!proc_mm) + pid = mm_idp->u.pid; + else { + cpu = get_cpu(); + pid = userspace_pid[cpu]; + } + + res = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); + if(res) + res = errno; + + if(proc_mm) + put_cpu(); + } + else { + void *stub_addr; + res = syscall_stub_data(mm_idp, (unsigned long *)desc, + (sizeof(*desc) + sizeof(long) - 1) & + ~(sizeof(long) - 1), + addr, &stub_addr); + if(!res){ + unsigned long args[] = { func, + (unsigned long)stub_addr, + sizeof(*desc), + 0, 0, 0 }; + res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, + 0, addr, done); + } + } + + if(proc_mm){ + /* This is the second part of special handling, that makes + * PTRACE_LDT possible to implement. + */ + if(current->active_mm && current->active_mm != &init_mm && + mm_idp != ¤t->active_mm->context.skas.id) + switch_mm_skas(¤t->active_mm->context.skas.id); + } + + return res; +} + +static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) +{ + int res, n; + struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { + .func = 0, + .bytecount = bytecount, + .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)}; + u32 cpu; + + if(ptrace_ldt.ptr == NULL) + return -ENOMEM; + + /* This is called from sys_modify_ldt only, so userspace_pid gives + * us the right number + */ + + cpu = get_cpu(); + res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, + (unsigned long) &ptrace_ldt); + put_cpu(); + if(res < 0) + goto out; + + n = copy_to_user(ptr, ptrace_ldt.ptr, res); + if(n != 0) + res = -EFAULT; + + out: + kfree(ptrace_ldt.ptr); + + return res; +} + +/* + * In skas mode, we hold our own ldt data in UML. + * Thus, the code implementing sys_modify_ldt_skas + * is very similar to (and mostly stolen from) sys_modify_ldt + * for arch/i386/kernel/ldt.c + * The routines copied and modified in part are: + * - read_ldt + * - read_default_ldt + * - write_ldt + * - sys_modify_ldt_skas + */ + +static int read_ldt(void __user * ptr, unsigned long bytecount) +{ + int i, err = 0; + unsigned long size; + uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; + + if(!ldt->entry_count) + goto out; + if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) + bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; + err = bytecount; + + if(ptrace_ldt){ + return read_ldt_from_host(ptr, bytecount); + } + + down(&ldt->semaphore); + if(ldt->entry_count <= LDT_DIRECT_ENTRIES){ + size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; + if(size > bytecount) + size = bytecount; + if(copy_to_user(ptr, ldt->entries, size)) + err = -EFAULT; + bytecount -= size; + ptr += size; + } + else { + for(i=0; ientry_count/LDT_ENTRIES_PER_PAGE && bytecount; + i++){ + size = PAGE_SIZE; + if(size > bytecount) + size = bytecount; + if(copy_to_user(ptr, ldt->pages[i], size)){ + err = -EFAULT; + break; + } + bytecount -= size; + ptr += size; + } + } + up(&ldt->semaphore); + + if(bytecount == 0 || err == -EFAULT) + goto out; + + if(clear_user(ptr, bytecount)) + err = -EFAULT; + +out: + return err; +} + +static int read_default_ldt(void __user * ptr, unsigned long bytecount) +{ + int err; + + if(bytecount > 5*LDT_ENTRY_SIZE) + bytecount = 5*LDT_ENTRY_SIZE; + + err = bytecount; + /* UML doesn't support lcall7 and lcall27. + * So, we don't really have a default ldt, but emulate + * an empty ldt of common host default ldt size. + */ + if(clear_user(ptr, bytecount)) + err = -EFAULT; + + return err; +} + +static int write_ldt(void __user * ptr, unsigned long bytecount, int func) +{ + uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; + struct mm_id * mm_idp = ¤t->mm->context.skas.id; + int i, err; + struct user_desc ldt_info; + struct ldt_entry entry0, *ldt_p; + void *addr = NULL; + + err = -EINVAL; + if(bytecount != sizeof(ldt_info)) + goto out; + err = -EFAULT; + if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) + goto out; + + err = -EINVAL; + if(ldt_info.entry_number >= LDT_ENTRIES) + goto out; + if(ldt_info.contents == 3){ + if (func == 1) + goto out; + if (ldt_info.seg_not_present == 0) + goto out; + } + + if(!ptrace_ldt) + down(&ldt->semaphore); + + err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); + if(err) + goto out_unlock; + else if(ptrace_ldt) { + /* With PTRACE_LDT available, this is used as a flag only */ + ldt->entry_count = 1; + goto out; + } + + if(ldt_info.entry_number >= ldt->entry_count && + ldt_info.entry_number >= LDT_DIRECT_ENTRIES){ + for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; + i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; + i++){ + if(i == 0) + memcpy(&entry0, ldt->entries, sizeof(entry0)); + ldt->pages[i] = (struct ldt_entry *) + __get_free_page(GFP_KERNEL|__GFP_ZERO); + if(!ldt->pages[i]){ + err = -ENOMEM; + /* Undo the change in host */ + memset(&ldt_info, 0, sizeof(ldt_info)); + write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); + goto out_unlock; + } + if(i == 0) { + memcpy(ldt->pages[0], &entry0, sizeof(entry0)); + memcpy(ldt->pages[0]+1, ldt->entries+1, + sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); + } + ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; + } + } + if(ldt->entry_count <= ldt_info.entry_number) + ldt->entry_count = ldt_info.entry_number + 1; + + if(ldt->entry_count <= LDT_DIRECT_ENTRIES) + ldt_p = ldt->entries + ldt_info.entry_number; + else + ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + + ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; + + if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && + (func == 1 || LDT_empty(&ldt_info))){ + ldt_p->a = 0; + ldt_p->b = 0; + } + else{ + if (func == 1) + ldt_info.useable = 0; + ldt_p->a = LDT_entry_a(&ldt_info); + ldt_p->b = LDT_entry_b(&ldt_info); + } + err = 0; + +out_unlock: + up(&ldt->semaphore); +out: + return err; +} + +static long do_modify_ldt_skas(int func, void __user *ptr, + unsigned long bytecount) +{ + int ret = -ENOSYS; + + switch (func) { + case 0: + ret = read_ldt(ptr, bytecount); + break; + case 1: + case 0x11: + ret = write_ldt(ptr, bytecount, func); + break; + case 2: + ret = read_default_ldt(ptr, bytecount); + break; + } + return ret; +} + +short dummy_list[9] = {0, -1}; +short * host_ldt_entries = NULL; + +void ldt_get_host_info(void) +{ + long ret; + struct ldt_entry * ldt; + int i, size, k, order; + + host_ldt_entries = dummy_list+1; + + for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); + + ldt = (struct ldt_entry *) + __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); + if(ldt == NULL) { + printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n"); + return; + } + + ret = modify_ldt(0, ldt, (1<ldt.semaphore); + + if(!from_mm){ + /* + * We have to initialize a clean ldt. + */ + if(proc_mm) { + /* + * If the new mm was created using proc_mm, host's + * default-ldt currently is assigned, which normally + * contains the call-gates for lcall7 and lcall27. + * To remove these gates, we simply write an empty + * entry as number 0 to the host. + */ + err = write_ldt_entry(&new_mm->id, 1, &desc, + &addr, 1); + } + else{ + /* + * Now we try to retrieve info about the ldt, we + * inherited from the host. All ldt-entries found + * will be reset in the following loop + */ + if(host_ldt_entries == NULL) + ldt_get_host_info(); + for(num_p=host_ldt_entries; *num_p != -1; num_p++){ + desc.entry_number = *num_p; + err = write_ldt_entry(&new_mm->id, 1, &desc, + &addr, *(num_p + 1) == -1); + if(err) + break; + } + } + new_mm->ldt.entry_count = 0; + } + else if (!ptrace_ldt) { + /* Our local LDT is used to supply the data for + * modify_ldt(READLDT), if PTRACE_LDT isn't available, + * i.e., we have to use the stub for modify_ldt, which + * can't handle the big read buffer of up to 64kB. + */ + down(&from_mm->ldt.semaphore); + if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ + memcpy(new_mm->ldt.entries, from_mm->ldt.entries, + sizeof(new_mm->ldt.entries)); + } + else{ + i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; + while(i-->0){ + page = __get_free_page(GFP_KERNEL|__GFP_ZERO); + if (!page){ + err = -ENOMEM; + break; + } + new_mm->ldt.pages[i] = (struct ldt_entry*)page; + memcpy(new_mm->ldt.pages[i], + from_mm->ldt.pages[i], PAGE_SIZE); + } + } + new_mm->ldt.entry_count = from_mm->ldt.entry_count; + up(&from_mm->ldt.semaphore); + } + + return err; +} + + +void free_ldt(struct mmu_context_skas * mm) +{ + int i; + + if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ + i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; + while(i-- > 0){ + free_page((long )mm->ldt.pages[i]); + } + } + mm->ldt.entry_count = 0; +} +#endif + +int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +{ + return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, + ptr, bytecount)); +} diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index 06c3633457a2..ea977df395a1 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -5,7 +5,7 @@ # #XXX: why into lib-y? -lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ +lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \ ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \ stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o @@ -14,7 +14,7 @@ obj-$(CONFIG_MODULES) += module.o um_module.o USER_OBJS := ptrace_user.o sigcontext.o -SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ +SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ thunk.S module.c include arch/um/scripts/Makefile.rules @@ -23,6 +23,7 @@ bitops.c-dir = lib csum-copy.S-dir = lib csum-partial.c-dir = lib csum-wrappers.c-dir = lib +ldt.c-dir = /arch/um/sys-i386 memcpy.S-dir = lib thunk.S-dir = lib module.c-dir = kernel diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 3259a4db4534..6acee5c4ada6 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -28,81 +28,6 @@ asmlinkage long sys_uname64(struct new_utsname __user * name) return err ? -EFAULT : 0; } -#ifdef CONFIG_MODE_TT -extern int modify_ldt(int func, void *ptr, unsigned long bytecount); - -long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -{ - /* XXX This should check VERIFY_WRITE depending on func, check this - * in i386 as well. - */ - if (!access_ok(VERIFY_READ, ptr, bytecount)) - return -EFAULT; - return(modify_ldt(func, ptr, bytecount)); -} -#endif - -#ifdef CONFIG_MODE_SKAS -extern int userspace_pid[]; - -#include "skas_ptrace.h" - -long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -{ - struct ptrace_ldt ldt; - void *buf; - int res, n; - - buf = kmalloc(bytecount, GFP_KERNEL); - if(buf == NULL) - return(-ENOMEM); - - res = 0; - - switch(func){ - case 1: - case 0x11: - res = copy_from_user(buf, ptr, bytecount); - break; - } - - if(res != 0){ - res = -EFAULT; - goto out; - } - - ldt = ((struct ptrace_ldt) { .func = func, - .ptr = buf, - .bytecount = bytecount }); -#warning Need to look up userspace_pid by cpu - res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt); - if(res < 0) - goto out; - - switch(func){ - case 0: - case 2: - n = res; - res = copy_to_user(ptr, buf, n); - if(res != 0) - res = -EFAULT; - else - res = n; - break; - } - - out: - kfree(buf); - return(res); -} -#endif - -long sys_modify_ldt(int func, void *ptr, unsigned long bytecount) -{ - return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, - ptr, bytecount)); -} - #ifdef CONFIG_MODE_TT extern long arch_prctl(int code, unsigned long addr); diff --git a/include/asm-um/ldt-i386.h b/include/asm-um/ldt-i386.h new file mode 100644 index 000000000000..b42662929b6c --- /dev/null +++ b/include/asm-um/ldt-i386.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Licensed under the GPL + * + * Author: Bodo Stroesser + */ + +#ifndef __ASM_LDT_I386_H +#define __ASM_LDT_I386_H + +#include "asm/semaphore.h" +#include "asm/arch/ldt.h" + +struct mmu_context_skas; +extern void ldt_host_info(void); +extern long init_new_ldt(struct mmu_context_skas * to_mm, + struct mmu_context_skas * from_mm); +extern void free_ldt(struct mmu_context_skas * mm); + +#define LDT_PAGES_MAX \ + ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE) +#define LDT_ENTRIES_PER_PAGE \ + (PAGE_SIZE/LDT_ENTRY_SIZE) +#define LDT_DIRECT_ENTRIES \ + ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE) + +struct ldt_entry { + __u32 a; + __u32 b; +}; + +typedef struct uml_ldt { + int entry_count; + struct semaphore semaphore; + union { + struct ldt_entry * pages[LDT_PAGES_MAX]; + struct ldt_entry entries[LDT_DIRECT_ENTRIES]; + }; +} uml_ldt_t; + +/* + * macros stolen from include/asm-i386/desc.h + */ +#define LDT_entry_a(info) \ + ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) + +#define LDT_entry_b(info) \ + (((info)->base_addr & 0xff000000) | \ + (((info)->base_addr & 0x00ff0000) >> 16) | \ + ((info)->limit & 0xf0000) | \ + (((info)->read_exec_only ^ 1) << 9) | \ + ((info)->contents << 10) | \ + (((info)->seg_not_present ^ 1) << 15) | \ + ((info)->seg_32bit << 22) | \ + ((info)->limit_in_pages << 23) | \ + ((info)->useable << 20) | \ + 0x7000) + +#define LDT_empty(info) (\ + (info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ + (info)->read_exec_only == 1 && \ + (info)->seg_32bit == 0 && \ + (info)->limit_in_pages == 0 && \ + (info)->seg_not_present == 1 && \ + (info)->useable == 0 ) + +#endif diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h index e908439d338a..4466ff6de0fd 100644 --- a/include/asm-um/ldt.h +++ b/include/asm-um/ldt.h @@ -1,3 +1,72 @@ +/* + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Licensed under the GPL + * + * Author: Bodo Stroesser + */ + +#ifndef __ASM_LDT_I386_H +#define __ASM_LDT_I386_H + +#include "asm/semaphore.h" +#include "asm/arch/ldt.h" + +struct mmu_context_skas; +extern void ldt_host_info(void); +extern long init_new_ldt(struct mmu_context_skas * to_mm, + struct mmu_context_skas * from_mm); +extern void free_ldt(struct mmu_context_skas * mm); + +#define LDT_PAGES_MAX \ + ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE) +#define LDT_ENTRIES_PER_PAGE \ + (PAGE_SIZE/LDT_ENTRY_SIZE) +#define LDT_DIRECT_ENTRIES \ + ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE) + +struct ldt_entry { + __u32 a; + __u32 b; +}; + +typedef struct uml_ldt { + int entry_count; + struct semaphore semaphore; + union { + struct ldt_entry * pages[LDT_PAGES_MAX]; + struct ldt_entry entries[LDT_DIRECT_ENTRIES]; + }; +} uml_ldt_t; + +/* + * macros stolen from include/asm-i386/desc.h + */ +#define LDT_entry_a(info) \ + ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) + +#define LDT_entry_b(info) \ + (((info)->base_addr & 0xff000000) | \ + (((info)->base_addr & 0x00ff0000) >> 16) | \ + ((info)->limit & 0xf0000) | \ + (((info)->read_exec_only ^ 1) << 9) | \ + ((info)->contents << 10) | \ + (((info)->seg_not_present ^ 1) << 15) | \ + ((info)->seg_32bit << 22) | \ + ((info)->limit_in_pages << 23) | \ + ((info)->useable << 20) | \ + 0x7000) + +#define LDT_empty(info) (\ + (info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ + (info)->read_exec_only == 1 && \ + (info)->seg_32bit == 0 && \ + (info)->limit_in_pages == 0 && \ + (info)->seg_not_present == 1 && \ + (info)->useable == 0 ) + +#endif #ifndef __UM_LDT_H #define __UM_LDT_H -- cgit v1.2.3 From 23f88fe4bffe01a0d29326789cb5813cd6f8158e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:59:00 -0800 Subject: [PATCH] include/asm-v850/ "extern inline" -> "static inline" "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Cc: Miles Bader Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-v850/atomic.h | 2 +- include/asm-v850/bitops.h | 6 +++--- include/asm-v850/delay.h | 4 ++-- include/asm-v850/hw_irq.h | 2 +- include/asm-v850/processor.h | 4 ++-- include/asm-v850/semaphore.h | 10 +++++----- include/asm-v850/system.h | 2 +- include/asm-v850/tlbflush.h | 4 ++-- include/asm-v850/uaccess.h | 2 +- include/asm-v850/unaligned.h | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h index 8284aa7363f2..395268a8c0de 100644 --- a/include/asm-v850/atomic.h +++ b/include/asm-v850/atomic.h @@ -31,7 +31,7 @@ typedef struct { int counter; } atomic_t; #define atomic_read(v) ((v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) -extern __inline__ int atomic_add_return (int i, volatile atomic_t *v) +static inline int atomic_add_return (int i, volatile atomic_t *v) { unsigned long flags; int res; diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h index 0e5c2f210872..b91e799763fd 100644 --- a/include/asm-v850/bitops.h +++ b/include/asm-v850/bitops.h @@ -30,7 +30,7 @@ * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ -extern __inline__ unsigned long ffz (unsigned long word) +static inline unsigned long ffz (unsigned long word) { unsigned long result = 0; @@ -135,7 +135,7 @@ extern __inline__ unsigned long ffz (unsigned long word) "m" (*((const char *)(addr) + ((nr) >> 3)))); \ __test_bit_res; \ }) -extern __inline__ int __test_bit (int nr, const void *addr) +static inline int __test_bit (int nr, const void *addr) { int res; __asm__ __volatile__ ("tst1 %1, [%2]; setf nz, %0" @@ -157,7 +157,7 @@ extern __inline__ int __test_bit (int nr, const void *addr) #define find_first_zero_bit(addr, size) \ find_next_zero_bit ((addr), (size), 0) -extern __inline__ int find_next_zero_bit(const void *addr, int size, int offset) +static inline int find_next_zero_bit(const void *addr, int size, int offset) { unsigned long *p = ((unsigned long *) addr) + (offset >> 5); unsigned long result = offset & ~31UL; diff --git a/include/asm-v850/delay.h b/include/asm-v850/delay.h index 1ce65d48a7c5..6d028e6b2354 100644 --- a/include/asm-v850/delay.h +++ b/include/asm-v850/delay.h @@ -16,7 +16,7 @@ #include -extern __inline__ void __delay(unsigned long loops) +static inline void __delay(unsigned long loops) { if (loops) __asm__ __volatile__ ("1: add -1, %0; bnz 1b" @@ -33,7 +33,7 @@ extern __inline__ void __delay(unsigned long loops) extern unsigned long loops_per_jiffy; -extern __inline__ void udelay(unsigned long usecs) +static inline void udelay(unsigned long usecs) { register unsigned long full_loops, part_loops; diff --git a/include/asm-v850/hw_irq.h b/include/asm-v850/hw_irq.h index 4bdc98edb9f8..a8aab4342712 100644 --- a/include/asm-v850/hw_irq.h +++ b/include/asm-v850/hw_irq.h @@ -1,7 +1,7 @@ #ifndef __V850_HW_IRQ_H__ #define __V850_HW_IRQ_H__ -extern inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i) +static inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i) { } diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h index d41f925f5182..98f929427d3d 100644 --- a/include/asm-v850/processor.h +++ b/include/asm-v850/processor.h @@ -59,7 +59,7 @@ struct thread_struct { /* Do necessary setup to start up a newly executed thread. */ -extern inline void start_thread (struct pt_regs *regs, +static inline void start_thread (struct pt_regs *regs, unsigned long pc, unsigned long usp) { regs->pc = pc; @@ -68,7 +68,7 @@ extern inline void start_thread (struct pt_regs *regs, } /* Free all resources held by a thread. */ -extern inline void release_thread (struct task_struct *dead_task) +static inline void release_thread (struct task_struct *dead_task) { } diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h index df6cdecf6c1f..735baaf3a16e 100644 --- a/include/asm-v850/semaphore.h +++ b/include/asm-v850/semaphore.h @@ -24,7 +24,7 @@ struct semaphore { #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC (name,1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC (name,0) -extern inline void sema_init (struct semaphore *sem, int val) +static inline void sema_init (struct semaphore *sem, int val) { *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); } @@ -52,14 +52,14 @@ extern int __down_interruptible (struct semaphore * sem); extern int __down_trylock (struct semaphore * sem); extern void __up (struct semaphore * sem); -extern inline void down (struct semaphore * sem) +static inline void down (struct semaphore * sem) { might_sleep(); if (atomic_dec_return (&sem->count) < 0) __down (sem); } -extern inline int down_interruptible (struct semaphore * sem) +static inline int down_interruptible (struct semaphore * sem) { int ret = 0; might_sleep(); @@ -68,7 +68,7 @@ extern inline int down_interruptible (struct semaphore * sem) return ret; } -extern inline int down_trylock (struct semaphore *sem) +static inline int down_trylock (struct semaphore *sem) { int ret = 0; if (atomic_dec_return (&sem->count) < 0) @@ -76,7 +76,7 @@ extern inline int down_trylock (struct semaphore *sem) return ret; } -extern inline void up (struct semaphore * sem) +static inline void up (struct semaphore * sem) { if (atomic_inc_return (&sem->count) <= 0) __up (sem); diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h index 20f4c738c04e..107decbd6e6c 100644 --- a/include/asm-v850/system.h +++ b/include/asm-v850/system.h @@ -81,7 +81,7 @@ static inline int irqs_disabled (void) ((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr)))) #define tas(ptr) (xchg ((ptr), 1)) -extern inline unsigned long __xchg (unsigned long with, +static inline unsigned long __xchg (unsigned long with, __volatile__ void *ptr, int size) { unsigned long tmp, flags; diff --git a/include/asm-v850/tlbflush.h b/include/asm-v850/tlbflush.h index 501e4498172c..5f2f85f636ea 100644 --- a/include/asm-v850/tlbflush.h +++ b/include/asm-v850/tlbflush.h @@ -56,12 +56,12 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, BUG (); } -extern inline void flush_tlb_kernel_page(unsigned long addr) +static inline void flush_tlb_kernel_page(unsigned long addr) { BUG (); } -extern inline void flush_tlb_pgtables(struct mm_struct *mm, +static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) { BUG (); diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h index 188b28597cf1..64563c409bb2 100644 --- a/include/asm-v850/uaccess.h +++ b/include/asm-v850/uaccess.h @@ -14,7 +14,7 @@ #define VERIFY_READ 0 #define VERIFY_WRITE 1 -extern inline int access_ok (int type, const void *addr, unsigned long size) +static inline int access_ok (int type, const void *addr, unsigned long size) { /* XXX I guess we should check against real ram bounds at least, and possibly make sure ADDR is not within the kernel. diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h index 65e38362142b..e30b18653a94 100644 --- a/include/asm-v850/unaligned.h +++ b/include/asm-v850/unaligned.h @@ -82,19 +82,19 @@ extern int __bug_unaligned_x(void *ptr); }) -extern inline void __put_unaligned_2(__u32 __v, register __u8 *__p) +static inline void __put_unaligned_2(__u32 __v, register __u8 *__p) { *__p++ = __v; *__p++ = __v >> 8; } -extern inline void __put_unaligned_4(__u32 __v, register __u8 *__p) +static inline void __put_unaligned_4(__u32 __v, register __u8 *__p) { __put_unaligned_2(__v >> 16, __p + 2); __put_unaligned_2(__v, __p); } -extern inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p) +static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p) { /* * tradeoff: 8 bytes of stack for all unaligned puts (2 -- cgit v1.2.3 From aa3a6f456f6ca162d3406a6e2c09a5c928833e4f Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Mon, 7 Nov 2005 00:59:01 -0800 Subject: [PATCH] xtensa: struct semaphore.sleepers initialization No one may sleep on us until we've been down()'d. So on allocation, initialize `sleepers' to 0, just like everyone else does. Signed-off-by: Arthur Othieno Acked-by: Christian Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-xtensa/semaphore.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h index 2a10e193b929..f10c3487cd4c 100644 --- a/include/asm-xtensa/semaphore.h +++ b/include/asm-xtensa/semaphore.h @@ -38,6 +38,7 @@ struct semaphore { static inline void sema_init (struct semaphore *sem, int val) { atomic_set(&sem->count, val); + sem->sleepers = 0; init_waitqueue_head(&sem->wait); } -- cgit v1.2.3 From 187dfc67b461058bbb84a923a17871ed54e10f30 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Nov 2005 00:59:07 -0800 Subject: [PATCH] s390: test_bit return value The test_bit function returns a non-boolean value, it returns 0,1,2,4,... instead of only 0 or 1. This causes wrongs results in the mincore system call. Check against 0 to get a proper boolean value. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/bitops.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 8651524217fd..b07c578b22ea 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h @@ -518,8 +518,8 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr static inline int __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) { - return (((volatile char *) addr) - [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))); + return ((((volatile char *) addr) + [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)))) != 0; } #define test_bit(nr,addr) \ -- cgit v1.2.3 From 4cd5b9f6df96494b8667deea71b61b66f783cca3 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 7 Nov 2005 00:59:09 -0800 Subject: [PATCH] s390: cleanup of include/asm-s390/vtoc.h Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/partitions/ibm.c | 15 +- include/asm-s390/vtoc.h | 505 +++++++++++++++--------------------------------- 2 files changed, 164 insertions(+), 356 deletions(-) (limited to 'include') diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index d59dcbf2bd4a..6327bcb2d73d 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -29,7 +29,7 @@ * cyl-cyl-head-head structure */ static inline int -cchh2blk (cchh_t *ptr, struct hd_geometry *geo) { +cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { return ptr->cc * geo->heads * geo->sectors + ptr->hh * geo->sectors; } @@ -40,7 +40,7 @@ cchh2blk (cchh_t *ptr, struct hd_geometry *geo) { * cyl-cyl-head-head-block structure */ static inline int -cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) { +cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { return ptr->cc * geo->heads * geo->sectors + ptr->hh * geo->sectors + ptr->b; @@ -56,7 +56,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; - volume_label_t *vlabel; + struct vtoc_volume_label *vlabel; unsigned char *data; Sector sect; @@ -64,7 +64,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) goto out_noinfo; if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) goto out_nogeo; - if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL) + if ((vlabel = kmalloc(sizeof(struct vtoc_volume_label), + GFP_KERNEL)) == NULL) goto out_novlab; if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || @@ -86,7 +87,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) strncpy(name, data + 8, 6); else strncpy(name, data + 4, 6); - memcpy (vlabel, data, sizeof(volume_label_t)); + memcpy (vlabel, data, sizeof(struct vtoc_volume_label)); put_dev_sector(sect); EBCASC(type, 4); @@ -129,9 +130,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) counter = 0; while ((data = read_dev_sector(bdev, blk*(blocksize/512), §)) != NULL) { - format1_label_t f1; + struct vtoc_format1_label f1; - memcpy(&f1, data, sizeof(format1_label_t)); + memcpy(&f1, data, sizeof(struct vtoc_format1_label)); put_dev_sector(sect); /* skip FMT4 / FMT5 / FMT7 labels */ diff --git a/include/asm-s390/vtoc.h b/include/asm-s390/vtoc.h index a14e34e80b88..41d369f38b0e 100644 --- a/include/asm-s390/vtoc.h +++ b/include/asm-s390/vtoc.h @@ -1,372 +1,179 @@ -#ifndef __KERNEL__ -#include -#include -#include -#include -#include -#include -#include -#include +/* + * include/asm-s390/vtoc.h + * + * This file contains volume label definitions for DASD devices. + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Volker Sameske + * + */ + +#ifndef _ASM_S390_VTOC_H +#define _ASM_S390_VTOC_H -#include -#include - -#include #include -#include -#include -#endif - - -#define LINE_LENGTH 80 -#define VTOC_START_CC 0x0 -#define VTOC_START_HH 0x1 -#define FIRST_USABLE_CYL 1 -#define FIRST_USABLE_TRK 2 - -#define DASD_3380_TYPE 13148 -#define DASD_3390_TYPE 13200 -#define DASD_9345_TYPE 37701 - -#define DASD_3380_VALUE 0xbb60 -#define DASD_3390_VALUE 0xe5a2 -#define DASD_9345_VALUE 0xbc98 - -#define VOLSER_LENGTH 6 -#define BIG_DISK_SIZE 0x10000 - -#define VTOC_ERROR "VTOC error:" - -typedef struct ttr +struct vtoc_ttr { - __u16 tt; - __u8 r; -} __attribute__ ((packed)) ttr_t; + __u16 tt; + __u8 r; +} __attribute__ ((packed)); -typedef struct cchhb +struct vtoc_cchhb { - __u16 cc; - __u16 hh; - __u8 b; -} __attribute__ ((packed)) cchhb_t; + __u16 cc; + __u16 hh; + __u8 b; +} __attribute__ ((packed)); -typedef struct cchh +struct vtoc_cchh { - __u16 cc; - __u16 hh; -} __attribute__ ((packed)) cchh_t; + __u16 cc; + __u16 hh; +} __attribute__ ((packed)); -typedef struct labeldate +struct vtoc_labeldate { - __u8 year; - __u16 day; -} __attribute__ ((packed)) labeldate_t; + __u8 year; + __u16 day; +} __attribute__ ((packed)); - -typedef struct volume_label +struct vtoc_volume_label { - char volkey[4]; /* volume key = volume label */ - char vollbl[4]; /* volume label */ - char volid[6]; /* volume identifier */ - __u8 security; /* security byte */ - cchhb_t vtoc; /* VTOC address */ - char res1[5]; /* reserved */ - char cisize[4]; /* CI-size for FBA,... */ - /* ...blanks for CKD */ - char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */ - char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */ - char res2[4]; /* reserved */ - char lvtoc[14]; /* owner code for LVTOC */ - char res3[29]; /* reserved */ -} __attribute__ ((packed)) volume_label_t; - - -typedef struct extent + char volkey[4]; /* volume key = volume label */ + char vollbl[4]; /* volume label */ + char volid[6]; /* volume identifier */ + __u8 security; /* security byte */ + struct vtoc_cchhb vtoc; /* VTOC address */ + char res1[5]; /* reserved */ + char cisize[4]; /* CI-size for FBA,... */ + /* ...blanks for CKD */ + char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */ + char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */ + char res2[4]; /* reserved */ + char lvtoc[14]; /* owner code for LVTOC */ + char res3[29]; /* reserved */ +} __attribute__ ((packed)); + +struct vtoc_extent { - __u8 typeind; /* extent type indicator */ - __u8 seqno; /* extent sequence number */ - cchh_t llimit; /* starting point of this extent */ - cchh_t ulimit; /* ending point of this extent */ -} __attribute__ ((packed)) extent_t; - + __u8 typeind; /* extent type indicator */ + __u8 seqno; /* extent sequence number */ + struct vtoc_cchh llimit; /* starting point of this extent */ + struct vtoc_cchh ulimit; /* ending point of this extent */ +} __attribute__ ((packed)); -typedef struct dev_const +struct vtoc_dev_const { - __u16 DS4DSCYL; /* number of logical cyls */ - __u16 DS4DSTRK; /* number of tracks in a logical cylinder */ - __u16 DS4DEVTK; /* device track length */ - __u8 DS4DEVI; /* non-last keyed record overhead */ - __u8 DS4DEVL; /* last keyed record overhead */ - __u8 DS4DEVK; /* non-keyed record overhead differential */ - __u8 DS4DEVFG; /* flag byte */ - __u16 DS4DEVTL; /* device tolerance */ - __u8 DS4DEVDT; /* number of DSCB's per track */ - __u8 DS4DEVDB; /* number of directory blocks per track */ -} __attribute__ ((packed)) dev_const_t; - - -typedef struct format1_label + __u16 DS4DSCYL; /* number of logical cyls */ + __u16 DS4DSTRK; /* number of tracks in a logical cylinder */ + __u16 DS4DEVTK; /* device track length */ + __u8 DS4DEVI; /* non-last keyed record overhead */ + __u8 DS4DEVL; /* last keyed record overhead */ + __u8 DS4DEVK; /* non-keyed record overhead differential */ + __u8 DS4DEVFG; /* flag byte */ + __u16 DS4DEVTL; /* device tolerance */ + __u8 DS4DEVDT; /* number of DSCB's per track */ + __u8 DS4DEVDB; /* number of directory blocks per track */ +} __attribute__ ((packed)); + +struct vtoc_format1_label { - char DS1DSNAM[44]; /* data set name */ - __u8 DS1FMTID; /* format identifier */ - char DS1DSSN[6]; /* data set serial number */ - __u16 DS1VOLSQ; /* volume sequence number */ - labeldate_t DS1CREDT; /* creation date: ydd */ - labeldate_t DS1EXPDT; /* expiration date */ - __u8 DS1NOEPV; /* number of extents on volume */ - __u8 DS1NOBDB; /* no. of bytes used in last direction blk */ - __u8 DS1FLAG1; /* flag 1 */ - char DS1SYSCD[13]; /* system code */ - labeldate_t DS1REFD; /* date last referenced */ - __u8 DS1SMSFG; /* system managed storage indicators */ - __u8 DS1SCXTF; /* sec. space extension flag byte */ - __u16 DS1SCXTV; /* secondary space extension value */ - __u8 DS1DSRG1; /* data set organisation byte 1 */ - __u8 DS1DSRG2; /* data set organisation byte 2 */ - __u8 DS1RECFM; /* record format */ - __u8 DS1OPTCD; /* option code */ - __u16 DS1BLKL; /* block length */ - __u16 DS1LRECL; /* record length */ - __u8 DS1KEYL; /* key length */ - __u16 DS1RKP; /* relative key position */ - __u8 DS1DSIND; /* data set indicators */ - __u8 DS1SCAL1; /* secondary allocation flag byte */ - char DS1SCAL3[3]; /* secondary allocation quantity */ - ttr_t DS1LSTAR; /* last used track and block on track */ - __u16 DS1TRBAL; /* space remaining on last used track */ - __u16 res1; /* reserved */ - extent_t DS1EXT1; /* first extent description */ - extent_t DS1EXT2; /* second extent description */ - extent_t DS1EXT3; /* third extent description */ - cchhb_t DS1PTRDS; /* possible pointer to f2 or f3 DSCB */ -} __attribute__ ((packed)) format1_label_t; - - -typedef struct format4_label + char DS1DSNAM[44]; /* data set name */ + __u8 DS1FMTID; /* format identifier */ + char DS1DSSN[6]; /* data set serial number */ + __u16 DS1VOLSQ; /* volume sequence number */ + struct vtoc_labeldate DS1CREDT; /* creation date: ydd */ + struct vtoc_labeldate DS1EXPDT; /* expiration date */ + __u8 DS1NOEPV; /* number of extents on volume */ + __u8 DS1NOBDB; /* no. of bytes used in last direction blk */ + __u8 DS1FLAG1; /* flag 1 */ + char DS1SYSCD[13]; /* system code */ + struct vtoc_labeldate DS1REFD; /* date last referenced */ + __u8 DS1SMSFG; /* system managed storage indicators */ + __u8 DS1SCXTF; /* sec. space extension flag byte */ + __u16 DS1SCXTV; /* secondary space extension value */ + __u8 DS1DSRG1; /* data set organisation byte 1 */ + __u8 DS1DSRG2; /* data set organisation byte 2 */ + __u8 DS1RECFM; /* record format */ + __u8 DS1OPTCD; /* option code */ + __u16 DS1BLKL; /* block length */ + __u16 DS1LRECL; /* record length */ + __u8 DS1KEYL; /* key length */ + __u16 DS1RKP; /* relative key position */ + __u8 DS1DSIND; /* data set indicators */ + __u8 DS1SCAL1; /* secondary allocation flag byte */ + char DS1SCAL3[3]; /* secondary allocation quantity */ + struct vtoc_ttr DS1LSTAR; /* last used track and block on track */ + __u16 DS1TRBAL; /* space remaining on last used track */ + __u16 res1; /* reserved */ + struct vtoc_extent DS1EXT1; /* first extent description */ + struct vtoc_extent DS1EXT2; /* second extent description */ + struct vtoc_extent DS1EXT3; /* third extent description */ + struct vtoc_cchhb DS1PTRDS; /* possible pointer to f2 or f3 DSCB */ +} __attribute__ ((packed)); + +struct vtoc_format4_label { - char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */ - __u8 DS4IDFMT; /* format identifier */ - cchhb_t DS4HPCHR; /* highest address of a format 1 DSCB */ - __u16 DS4DSREC; /* number of available DSCB's */ - cchh_t DS4HCCHH; /* CCHH of next available alternate track */ - __u16 DS4NOATK; /* number of remaining alternate tracks */ - __u8 DS4VTOCI; /* VTOC indicators */ - __u8 DS4NOEXT; /* number of extents in VTOC */ - __u8 DS4SMSFG; /* system managed storage indicators */ - __u8 DS4DEVAC; /* number of alternate cylinders. - Subtract from first two bytes of - DS4DEVSZ to get number of usable - cylinders. can be zero. valid - only if DS4DEVAV on. */ - dev_const_t DS4DEVCT; /* device constants */ - char DS4AMTIM[8]; /* VSAM time stamp */ - char DS4AMCAT[3]; /* VSAM catalog indicator */ - char DS4R2TIM[8]; /* VSAM volume/catalog match time stamp */ - char res1[5]; /* reserved */ - char DS4F6PTR[5]; /* pointer to first format 6 DSCB */ - extent_t DS4VTOCE; /* VTOC extent description */ - char res2[10]; /* reserved */ - __u8 DS4EFLVL; /* extended free-space management level */ - cchhb_t DS4EFPTR; /* pointer to extended free-space info */ - char res3[9]; /* reserved */ -} __attribute__ ((packed)) format4_label_t; - - -typedef struct ds5ext + char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */ + __u8 DS4IDFMT; /* format identifier */ + struct vtoc_cchhb DS4HPCHR; /* highest address of a format 1 DSCB */ + __u16 DS4DSREC; /* number of available DSCB's */ + struct vtoc_cchh DS4HCCHH; /* CCHH of next available alternate track */ + __u16 DS4NOATK; /* number of remaining alternate tracks */ + __u8 DS4VTOCI; /* VTOC indicators */ + __u8 DS4NOEXT; /* number of extents in VTOC */ + __u8 DS4SMSFG; /* system managed storage indicators */ + __u8 DS4DEVAC; /* number of alternate cylinders. + * Subtract from first two bytes of + * DS4DEVSZ to get number of usable + * cylinders. can be zero. valid + * only if DS4DEVAV on. */ + struct vtoc_dev_const DS4DEVCT; /* device constants */ + char DS4AMTIM[8]; /* VSAM time stamp */ + char DS4AMCAT[3]; /* VSAM catalog indicator */ + char DS4R2TIM[8]; /* VSAM volume/catalog match time stamp */ + char res1[5]; /* reserved */ + char DS4F6PTR[5]; /* pointer to first format 6 DSCB */ + struct vtoc_extent DS4VTOCE; /* VTOC extent description */ + char res2[10]; /* reserved */ + __u8 DS4EFLVL; /* extended free-space management level */ + struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */ + char res3[9]; /* reserved */ +} __attribute__ ((packed)); + +struct vtoc_ds5ext { - __u16 t; /* RTA of the first track of free extent */ - __u16 fc; /* number of whole cylinders in free ext. */ - __u8 ft; /* number of remaining free tracks */ -} __attribute__ ((packed)) ds5ext_t; - + __u16 t; /* RTA of the first track of free extent */ + __u16 fc; /* number of whole cylinders in free ext. */ + __u8 ft; /* number of remaining free tracks */ +} __attribute__ ((packed)); -typedef struct format5_label +struct vtoc_format5_label { - char DS5KEYID[4]; /* key identifier */ - ds5ext_t DS5AVEXT; /* first available (free-space) extent. */ - ds5ext_t DS5EXTAV[7]; /* seven available extents */ - __u8 DS5FMTID; /* format identifier */ - ds5ext_t DS5MAVET[18]; /* eighteen available extents */ - cchhb_t DS5PTRDS; /* pointer to next format5 DSCB */ -} __attribute__ ((packed)) format5_label_t; - - -typedef struct ds7ext + char DS5KEYID[4]; /* key identifier */ + struct vtoc_ds5ext DS5AVEXT; /* first available (free-space) extent. */ + struct vtoc_ds5ext DS5EXTAV[7]; /* seven available extents */ + __u8 DS5FMTID; /* format identifier */ + struct vtoc_ds5ext DS5MAVET[18]; /* eighteen available extents */ + struct vtoc_cchhb DS5PTRDS; /* pointer to next format5 DSCB */ +} __attribute__ ((packed)); + +struct vtoc_ds7ext { - __u32 a; /* starting RTA value */ - __u32 b; /* ending RTA value + 1 */ -} __attribute__ ((packed)) ds7ext_t; + __u32 a; /* starting RTA value */ + __u32 b; /* ending RTA value + 1 */ +} __attribute__ ((packed)); - -typedef struct format7_label +struct vtoc_format7_label { - char DS7KEYID[4]; /* key identifier */ - ds7ext_t DS7EXTNT[5]; /* space for 5 extent descriptions */ - __u8 DS7FMTID; /* format identifier */ - ds7ext_t DS7ADEXT[11]; /* space for 11 extent descriptions */ - char res1[2]; /* reserved */ - cchhb_t DS7PTRDS; /* pointer to next FMT7 DSCB */ -} __attribute__ ((packed)) format7_label_t; - - -char * vtoc_ebcdic_enc ( - unsigned char source[LINE_LENGTH], - unsigned char target[LINE_LENGTH], - int l); -char * vtoc_ebcdic_dec ( - unsigned char source[LINE_LENGTH], - unsigned char target[LINE_LENGTH], - int l); -void vtoc_set_extent ( - extent_t * ext, - __u8 typeind, - __u8 seqno, - cchh_t * lower, - cchh_t * upper); -void vtoc_set_cchh ( - cchh_t * addr, - __u16 cc, - __u16 hh); -void vtoc_set_cchhb ( - cchhb_t * addr, - __u16 cc, - __u16 hh, - __u8 b); -void vtoc_set_date ( - labeldate_t * d, - __u8 year, - __u16 day); - -void vtoc_volume_label_init ( - volume_label_t *vlabel); - -int vtoc_read_volume_label ( - char * device, - unsigned long vlabel_start, - volume_label_t * vlabel); - -int vtoc_write_volume_label ( - char *device, - unsigned long vlabel_start, - volume_label_t *vlabel); - -void vtoc_volume_label_set_volser ( - volume_label_t *vlabel, - char *volser); - -char *vtoc_volume_label_get_volser ( - volume_label_t *vlabel, - char *volser); - -void vtoc_volume_label_set_key ( - volume_label_t *vlabel, - char *key); - -void vtoc_volume_label_set_label ( - volume_label_t *vlabel, - char *lbl); - -char *vtoc_volume_label_get_label ( - volume_label_t *vlabel, - char *lbl); - -void vtoc_read_label ( - char *device, - unsigned long position, - format1_label_t *f1, - format4_label_t *f4, - format5_label_t *f5, - format7_label_t *f7); - -void vtoc_write_label ( - char *device, - unsigned long position, - format1_label_t *f1, - format4_label_t *f4, - format5_label_t *f5, - format7_label_t *f7); - - -void vtoc_init_format1_label ( - char *volid, - unsigned int blksize, - extent_t *part_extent, - format1_label_t *f1); - - -void vtoc_init_format4_label ( - format4_label_t *f4lbl, - unsigned int usable_partitions, - unsigned int cylinders, - unsigned int tracks, - unsigned int blocks, - unsigned int blksize, - __u16 dev_type); - -void vtoc_update_format4_label ( - format4_label_t *f4, - cchhb_t *highest_f1, - __u16 unused_update); - - -void vtoc_init_format5_label ( - format5_label_t *f5); - -void vtoc_update_format5_label_add ( - format5_label_t *f5, - int verbose, - int cyl, - int trk, - __u16 a, - __u16 b, - __u8 c); - -void vtoc_update_format5_label_del ( - format5_label_t *f5, - int verbose, - int cyl, - int trk, - __u16 a, - __u16 b, - __u8 c); - - -void vtoc_init_format7_label ( - format7_label_t *f7); - -void vtoc_update_format7_label_add ( - format7_label_t *f7, - int verbose, - __u32 a, - __u32 b); - -void vtoc_update_format7_label_del ( - format7_label_t *f7, - int verbose, - __u32 a, - __u32 b); - - -void vtoc_set_freespace( - format4_label_t *f4, - format5_label_t *f5, - format7_label_t *f7, - char ch, - int verbose, - __u32 start, - __u32 stop, - int cyl, - int trk); - - - - - - - - - - - - + char DS7KEYID[4]; /* key identifier */ + struct vtoc_ds7ext DS7EXTNT[5]; /* space for 5 extent descriptions */ + __u8 DS7FMTID; /* format identifier */ + struct vtoc_ds7ext DS7ADEXT[11]; /* space for 11 extent descriptions */ + char res1[2]; /* reserved */ + struct vtoc_cchhb DS7PTRDS; /* pointer to next FMT7 DSCB */ +} __attribute__ ((packed)); + +#endif /* _ASM_S390_VTOC_H */ -- cgit v1.2.3 From 1047aa7723997620ba03a21429d2c5d923ebf48f Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 7 Nov 2005 00:59:11 -0800 Subject: [PATCH] s390: const pointer uaccess Using __typeof__(*ptr) on a pointer to const makes the __x variable in __get_user const as well. The latest gcc will refuse to write to it. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/uaccess.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index 38a5cf8ab9e3..10a619da4761 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h @@ -200,21 +200,37 @@ extern int __put_user_bad(void) __attribute__((noreturn)); #define __get_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) __x; \ int __gu_err; \ __chk_user_ptr(ptr); \ switch (sizeof(*(ptr))) { \ - case 1: \ - case 2: \ - case 4: \ - case 8: \ + case 1: { \ + unsigned char __x; \ + __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ + break; \ + }; \ + case 2: { \ + unsigned short __x; \ + __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ + break; \ + }; \ + case 4: { \ + unsigned int __x; \ + __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ + break; \ + }; \ + case 8: { \ + unsigned long long __x; \ __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ break; \ + }; \ default: \ __get_user_bad(); \ break; \ } \ - (x) = __x; \ __gu_err; \ }) -- cgit v1.2.3 From 9f46080c41d5f3f7c00b4e169ba4b0b2865258bf Mon Sep 17 00:00:00 2001 From: Matt Helsley Date: Mon, 7 Nov 2005 00:59:16 -0800 Subject: [PATCH] Process Events Connector This patch adds a connector that reports fork, exec, id change, and exit events for all processes to userspace. It replaces the fork_advisor patch that ELSA is currently using. Applications that may find these events useful include accounting/auditing (e.g. ELSA), system activity monitoring (e.g. top), security, and resource management (e.g. CKRM). Signed-off-by: Matt Helsley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/connector/Kconfig | 8 ++ drivers/connector/Makefile | 1 + drivers/connector/cn_proc.c | 222 ++++++++++++++++++++++++++++++++++++++++++++ fs/exec.c | 2 + include/linux/cn_proc.h | 127 +++++++++++++++++++++++++ include/linux/connector.h | 6 ++ kernel/exit.c | 2 + kernel/fork.c | 2 + kernel/sys.c | 9 ++ 9 files changed, 379 insertions(+) create mode 100644 drivers/connector/cn_proc.c create mode 100644 include/linux/cn_proc.h (limited to 'include') diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig index 0bc2059c1e08..e0bdc0db9640 100644 --- a/drivers/connector/Kconfig +++ b/drivers/connector/Kconfig @@ -10,4 +10,12 @@ config CONNECTOR Connector support can also be built as a module. If so, the module will be called cn.ko. +config PROC_EVENTS + boolean "Report process events to userspace" + depends on CONNECTOR=y + default y + ---help--- + Provide a connector that reports process events to userspace. Send + events such as fork, exec, id change (uid, gid, suid, etc), and exit. + endmenu diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile index 12ca79e8234d..1f255e46e916 100644 --- a/drivers/connector/Makefile +++ b/drivers/connector/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_CONNECTOR) += cn.o +obj-$(CONFIG_PROC_EVENTS) += cn_proc.o cn-y += cn_queue.o connector.o diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c new file mode 100644 index 000000000000..fcdf0fff13a6 --- /dev/null +++ b/drivers/connector/cn_proc.c @@ -0,0 +1,222 @@ +/* + * cn_proc.c - process events connector + * + * Copyright (C) Matt Helsley, IBM Corp. 2005 + * Based on cn_fork.c by Guillaume Thouvenin + * Original copyright notice follows: + * Copyright (C) 2005 BULL SA. + * + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) + +static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); +static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; + +/* proc_counts is used as the sequence number of the netlink message */ +static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; + +static inline void get_seq(__u32 *ts, int *cpu) +{ + *ts = get_cpu_var(proc_event_counts)++; + *cpu = smp_processor_id(); + put_cpu_var(proc_counts); +} + +void proc_fork_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_FORK; + ev->event_data.fork.parent_pid = task->real_parent->pid; + ev->event_data.fork.parent_tgid = task->real_parent->tgid; + ev->event_data.fork.child_pid = task->pid; + ev->event_data.fork.child_tgid = task->tgid; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + /* If cn_netlink_send() failed, the data is not sent */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_exec_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_EXEC; + ev->event_data.exec.process_pid = task->pid; + ev->event_data.exec.process_tgid = task->tgid; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_id_connector(struct task_struct *task, int which_id) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + ev->what = which_id; + ev->event_data.id.process_pid = task->pid; + ev->event_data.id.process_tgid = task->tgid; + if (which_id == PROC_EVENT_UID) { + ev->event_data.id.r.ruid = task->uid; + ev->event_data.id.e.euid = task->euid; + } else if (which_id == PROC_EVENT_GID) { + ev->event_data.id.r.rgid = task->gid; + ev->event_data.id.e.egid = task->egid; + } else + return; + get_seq(&msg->seq, &ev->cpu); + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_exit_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_EXIT; + ev->event_data.exit.process_pid = task->pid; + ev->event_data.exit.process_tgid = task->tgid; + ev->event_data.exit.exit_code = task->exit_code; + ev->event_data.exit.exit_signal = task->exit_signal; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +/* + * Send an acknowledgement message to userspace + * + * Use 0 for success, EFOO otherwise. + * Note: this is the negative of conventional kernel error + * values because it's not being returned via syscall return + * mechanisms. + */ +static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + msg->seq = rcvd_seq; + ev->cpu = -1; + ev->what = PROC_EVENT_NONE; + ev->event_data.ack.err = err; + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = rcvd_ack + 1; + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +/** + * cn_proc_mcast_ctl + * @data: message sent from userspace via the connector + */ +static void cn_proc_mcast_ctl(void *data) +{ + struct cn_msg *msg = data; + enum proc_cn_mcast_op *mc_op = NULL; + int err = 0; + + if (msg->len != sizeof(*mc_op)) + return; + + mc_op = (enum proc_cn_mcast_op*)msg->data; + switch (*mc_op) { + case PROC_CN_MCAST_LISTEN: + atomic_inc(&proc_event_num_listeners); + break; + case PROC_CN_MCAST_IGNORE: + atomic_dec(&proc_event_num_listeners); + break; + default: + err = EINVAL; + break; + } + cn_proc_ack(err, msg->seq, msg->ack); +} + +/* + * cn_proc_init - initialization entry point + * + * Adds the connector callback to the connector driver. + */ +static int __init cn_proc_init(void) +{ + int err; + + if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc", + &cn_proc_mcast_ctl))) { + printk(KERN_WARNING "cn_proc failed to register\n"); + return err; + } + return 0; +} + +module_init(cn_proc_init); diff --git a/fs/exec.c b/fs/exec.c index 10d493fea7ce..ce76b33f25ac 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -1096,6 +1097,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; + proc_exec_connector(current); return retval; } read_lock(&binfmt_lock); diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h new file mode 100644 index 000000000000..70ab56317380 --- /dev/null +++ b/include/linux/cn_proc.h @@ -0,0 +1,127 @@ +/* + * cn_proc.h - process events connector + * + * Copyright (C) Matt Helsley, IBM Corp. 2005 + * Based on cn_fork.h by Nguyen Anh Quynh and Guillaume Thouvenin + * Original copyright notice follows: + * Copyright (C) 2005 Nguyen Anh Quynh + * Copyright (C) 2005 Guillaume Thouvenin + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CN_PROC_H +#define CN_PROC_H + +#include +#include + +/* + * Userspace sends this enum to register with the kernel that it is listening + * for events on the connector. + */ +enum proc_cn_mcast_op { + PROC_CN_MCAST_LISTEN = 1, + PROC_CN_MCAST_IGNORE = 2 +}; + +/* + * From the user's point of view, the process + * ID is the thread group ID and thread ID is the internal + * kernel "pid". So, fields are assigned as follow: + * + * In user space - In kernel space + * + * parent process ID = parent->tgid + * parent thread ID = parent->pid + * child process ID = child->tgid + * child thread ID = child->pid + */ + +struct proc_event { + enum what { + /* Use successive bits so the enums can be used to record + * sets of events as well + */ + PROC_EVENT_NONE = 0x00000000, + PROC_EVENT_FORK = 0x00000001, + PROC_EVENT_EXEC = 0x00000002, + PROC_EVENT_UID = 0x00000004, + PROC_EVENT_GID = 0x00000040, + /* "next" should be 0x00000400 */ + /* "last" is the last process event: exit */ + PROC_EVENT_EXIT = 0x80000000 + } what; + __u32 cpu; + union { /* must be last field of proc_event struct */ + struct { + __u32 err; + } ack; + + struct fork_proc_event { + pid_t parent_pid; + pid_t parent_tgid; + pid_t child_pid; + pid_t child_tgid; + } fork; + + struct exec_proc_event { + pid_t process_pid; + pid_t process_tgid; + } exec; + + struct id_proc_event { + pid_t process_pid; + pid_t process_tgid; + union { + uid_t ruid; /* current->uid */ + gid_t rgid; /* current->gid */ + } r; + union { + uid_t euid; + gid_t egid; + } e; + } id; + + struct exit_proc_event { + pid_t process_pid; + pid_t process_tgid; + __u32 exit_code, exit_signal; + } exit; + } event_data; +}; + +#ifdef __KERNEL__ +#ifdef CONFIG_PROC_EVENTS +void proc_fork_connector(struct task_struct *task); +void proc_exec_connector(struct task_struct *task); +void proc_id_connector(struct task_struct *task, int which_id); +void proc_exit_connector(struct task_struct *task); +#else +static inline void proc_fork_connector(struct task_struct *task) +{} + +static inline void proc_exec_connector(struct task_struct *task) +{} + +static inline void proc_id_connector(struct task_struct *task, + int which_id) +{} + +static inline void proc_exit_connector(struct task_struct *task) +{} +#endif /* CONFIG_PROC_EVENTS */ +#endif /* __KERNEL__ */ +#endif /* CN_PROC_H */ diff --git a/include/linux/connector.h b/include/linux/connector.h index 95952cc1f525..c5769c6585f4 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -27,6 +27,12 @@ #define CN_IDX_CONNECTOR 0xffffffff #define CN_VAL_CONNECTOR 0xffffffff +/* + * Process Events connector unique ids -- used for message routing + */ +#define CN_IDX_PROC 0x1 +#define CN_VAL_PROC 0x1 + #define CN_NETLINK_USERS 1 /* diff --git a/kernel/exit.c b/kernel/exit.c index 537394b25e8d..452a1d116178 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -863,6 +864,7 @@ fastcall NORET_TYPE void do_exit(long code) module_put(tsk->binfmt->module); tsk->exit_code = code; + proc_exit_connector(tsk); exit_notify(tsk); #ifdef CONFIG_NUMA mpol_free(tsk->mempolicy); diff --git a/kernel/fork.c b/kernel/fork.c index 8a069612eac3..efac2c58ec7d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -1143,6 +1144,7 @@ static task_t *copy_process(unsigned long clone_flags, __get_cpu_var(process_counts)++; } + proc_fork_connector(p); if (!current->signal->tty && p->signal->tty) p->signal->tty = NULL; diff --git a/kernel/sys.c b/kernel/sys.c index 2fa1ed18123c..1e1f41b3fdf6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -623,6 +624,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) current->egid = new_egid; current->gid = new_rgid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -662,6 +664,7 @@ asmlinkage long sys_setgid(gid_t gid) return -EPERM; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -751,6 +754,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) current->fsuid = current->euid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); } @@ -798,6 +802,7 @@ asmlinkage long sys_setuid(uid_t uid) current->suid = new_suid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); } @@ -846,6 +851,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) current->suid = suid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); } @@ -898,6 +904,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) current->sgid = sgid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -940,6 +947,7 @@ asmlinkage long sys_setfsuid(uid_t uid) } key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS); @@ -968,6 +976,7 @@ asmlinkage long sys_setfsgid(gid_t gid) } current->fsgid = gid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); } return old_fsgid; } -- cgit v1.2.3 From 665a7583f32ab5b3bfe7a4d88da506542f7cdd75 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 7 Nov 2005 00:59:17 -0800 Subject: [PATCH] Remove hlist_for_each_rcu() API, convert existing use to hlist_for_each_entry_rcu Remove the hlist_for_each_rcu() API, which is used only in one place, and is trivially converted to hlist_for_each_entry_rcu(), making the code shorter and more readable. Any out-of-tree uses may be similarly converted. Signed-off-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/RCU/whatisRCU.txt | 2 -- fs/dcache.c | 10 ++++------ include/linux/list.h | 13 ++++--------- 3 files changed, 8 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 354d89c78377..15da16861fa3 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -772,8 +772,6 @@ RCU pointer/list traversal: list_for_each_entry_rcu list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_entry_continue_rcu) - hlist_for_each_rcu (to be deprecated in favor of - hlist_for_each_entry_rcu) hlist_for_each_entry_rcu RCU pointer update: diff --git a/fs/dcache.c b/fs/dcache.c index e90512ed35a4..17e439138681 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -644,7 +644,7 @@ void shrink_dcache_parent(struct dentry * parent) * * Prune the dentries that are anonymous * - * parsing d_hash list does not hlist_for_each_rcu() as it + * parsing d_hash list does not hlist_for_each_entry_rcu() as it * done under dcache_lock. * */ @@ -1043,15 +1043,13 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) struct hlist_head *head = d_hash(parent,hash); struct dentry *found = NULL; struct hlist_node *node; + struct dentry *dentry; rcu_read_lock(); - hlist_for_each_rcu(node, head) { - struct dentry *dentry; + hlist_for_each_entry_rcu(dentry, node, head, d_hash) { struct qstr *qstr; - dentry = hlist_entry(node, struct dentry, d_hash); - if (dentry->d_name.hash != hash) continue; if (dentry->d_parent != parent) @@ -1123,7 +1121,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) spin_lock(&dcache_lock); base = d_hash(dparent, dentry->d_name.hash); hlist_for_each(lhp,base) { - /* hlist_for_each_rcu() not required for d_hash list + /* hlist_for_each_entry_rcu() not required for d_hash list * as it is parsed under dcache_lock */ if (dentry == hlist_entry(lhp, struct dentry, d_hash)) { diff --git a/include/linux/list.h b/include/linux/list.h index 084971f333fe..fbfca73355a3 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -601,7 +601,7 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. Regardless of the type of CPU, the * list-traversal primitive must be guarded by rcu_read_lock(). */ @@ -650,7 +650,7 @@ static inline void hlist_add_after(struct hlist_node *n, * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. */ static inline void hlist_add_before_rcu(struct hlist_node *n, @@ -675,7 +675,7 @@ static inline void hlist_add_before_rcu(struct hlist_node *n, * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. */ static inline void hlist_add_after_rcu(struct hlist_node *prev, @@ -699,11 +699,6 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ pos = n) -#define hlist_for_each_rcu(pos, head) \ - for ((pos) = (head)->first; \ - rcu_dereference((pos)) && ({ prefetch((pos)->next); 1; }); \ - (pos) = (pos)->next) - /** * hlist_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop counter. @@ -756,7 +751,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, /** * hlist_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. + * @tpos: the type * to use as a loop counter. * @pos: the &struct hlist_node to use as a loop counter. * @head: the head for your list. * @member: the name of the hlist_node within the struct. -- cgit v1.2.3 From bf8f972d3a1daf969cf44f64cc36d53bfd76441f Mon Sep 17 00:00:00 2001 From: Badari Pulavarty Date: Mon, 7 Nov 2005 00:59:27 -0800 Subject: [PATCH] SHM_NORESERVE flags for shmget() Add SHM_NORESERVE functionality similar to MAP_NORESERVE for shared memory segments. This is mainly to avoid abuse of OVERCOMMIT_ALWAYS and this flag is ignored for OVERCOMMIT_NEVER. Signed-off-by: Badari Pulavarty Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/shm.h | 1 + ipc/shm.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/shm.h b/include/linux/shm.h index 80113a1f60bc..a2c896ad0bef 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -92,6 +92,7 @@ struct shmid_kernel /* private to the kernel */ #define SHM_DEST 01000 /* segment will be destroyed on last detach */ #define SHM_LOCKED 02000 /* segment will not be swapped */ #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ +#define SHM_NORESERVE 010000 /* don't check for reservations */ #ifdef CONFIG_SYSVIPC long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr); diff --git a/ipc/shm.c b/ipc/shm.c index b58c651d31ae..587d836d80d9 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -212,8 +212,16 @@ static int newseg (key_t key, int shmflg, size_t size) file = hugetlb_zero_setup(size); shp->mlock_user = current->user; } else { + int acctflag = VM_ACCOUNT; + /* + * Do not allow no accounting for OVERCOMMIT_NEVER, even + * if it's asked for. + */ + if ((shmflg & SHM_NORESERVE) && + sysctl_overcommit_memory != OVERCOMMIT_NEVER) + acctflag = 0; sprintf (name, "SYSV%08x", key); - file = shmem_file_setup(name, size, VM_ACCOUNT); + file = shmem_file_setup(name, size, acctflag); } error = PTR_ERR(file); if (IS_ERR(file)) -- cgit v1.2.3 From 7361f4d8ca65d23a18ba009b4484612183332c2f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:59:28 -0800 Subject: [PATCH] readahead commentary Add a few comments surrounding the generic readahead API. Also convert some ulongs into pgoff_t: the identifier for PAGE_CACHE_SIZE offsets into pagecache. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 8 ++++---- mm/readahead.c | 31 ++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index 5c1fb0a2e806..7b115feca4df 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -932,13 +932,13 @@ int write_one_page(struct page *page, int wait); * turning readahead off */ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read); + pgoff_t offset, unsigned long nr_to_read); int force_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read); -unsigned long page_cache_readahead(struct address_space *mapping, + pgoff_t offset, unsigned long nr_to_read); +unsigned long page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, struct file *filp, - unsigned long offset, + pgoff_t offset, unsigned long size); void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra, pgoff_t offset); diff --git a/mm/readahead.c b/mm/readahead.c index d0b50034e245..72e7adbb87c7 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -254,7 +254,7 @@ out: */ static int __do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { struct inode *inode = mapping->host; struct page *page; @@ -274,7 +274,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, */ read_lock_irq(&mapping->tree_lock); for (page_idx = 0; page_idx < nr_to_read; page_idx++) { - unsigned long page_offset = offset + page_idx; + pgoff_t page_offset = offset + page_idx; if (page_offset > end_index) break; @@ -311,7 +311,7 @@ out: * memory at once. */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { int ret = 0; @@ -368,7 +368,7 @@ static inline int check_ra_success(struct file_ra_state *ra, * request queues. */ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { if (bdi_read_congested(mapping->backing_dev_info)) return -1; @@ -385,7 +385,7 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, */ static int blockable_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read, + pgoff_t offset, unsigned long nr_to_read, struct file_ra_state *ra, int block) { int actual; @@ -430,14 +430,27 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp, return ret; } -/* - * page_cache_readahead is the main function. If performs the adaptive +/** + * page_cache_readahead - generic adaptive readahead + * @mapping: address_space which holds the pagecache and I/O vectors + * @ra: file_ra_state which holds the readahead state + * @filp: passed on to ->readpage() and ->readpages() + * @offset: start offset into @mapping, in PAGE_CACHE_SIZE units + * @req_size: hint: total size of the read which the caller is performing in + * PAGE_CACHE_SIZE units + * + * page_cache_readahead() is the main function. If performs the adaptive * readahead window size management and submits the readahead I/O. + * + * Note that @filp is purely used for passing on to the ->readpage[s]() + * handler: it may refer to a different file from @mapping (so we may not use + * @filp->f_mapping or @filp->f_dentry->d_inode here). + * Also, @ra may not be equal to &@filp->f_ra. + * */ unsigned long page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, - struct file *filp, unsigned long offset, - unsigned long req_size) + struct file *filp, pgoff_t offset, unsigned long req_size) { unsigned long max, newsize; int sequential; -- cgit v1.2.3 From a43313668f62a06e14c915b8c8994fc8a1257394 Mon Sep 17 00:00:00 2001 From: Hans Reiser Date: Mon, 7 Nov 2005 00:59:29 -0800 Subject: [PATCH] reiser4: add radix_tree_lookup_slot() Reiser4 uses radix trees to solve a trouble reiser4_readdir has serving nfs requests. Unfortunately, radix tree api lacks an operation suitable for modifying existing entry. This patch adds radix_tree_lookup_slot which returns pointer to found item within the tree. That location can be then updated. Both Nick and Christoph Lameter have patches which need this as well. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/radix-tree.h | 1 + lib/radix-tree.c | 51 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 9f0f9281f42a..36e5d269612f 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -46,6 +46,7 @@ do { \ int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); void *radix_tree_lookup(struct radix_tree_root *, unsigned long); +void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); void *radix_tree_delete(struct radix_tree_root *, unsigned long); unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, diff --git a/lib/radix-tree.c b/lib/radix-tree.c index d1c057e71b68..88511c3805ad 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -281,35 +281,60 @@ int radix_tree_insert(struct radix_tree_root *root, } EXPORT_SYMBOL(radix_tree_insert); -/** - * radix_tree_lookup - perform lookup operation on a radix tree - * @root: radix tree root - * @index: index key - * - * Lookup the item at the position @index in the radix tree @root. - */ -void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) +static inline void **__lookup_slot(struct radix_tree_root *root, + unsigned long index) { unsigned int height, shift; - struct radix_tree_node *slot; + struct radix_tree_node **slot; height = root->height; if (index > radix_tree_maxindex(height)) return NULL; shift = (height-1) * RADIX_TREE_MAP_SHIFT; - slot = root->rnode; + slot = &root->rnode; while (height > 0) { - if (slot == NULL) + if (*slot == NULL) return NULL; - slot = slot->slots[(index >> shift) & RADIX_TREE_MAP_MASK]; + slot = (struct radix_tree_node **) + ((*slot)->slots + + ((index >> shift) & RADIX_TREE_MAP_MASK)); shift -= RADIX_TREE_MAP_SHIFT; height--; } - return slot; + return (void **)slot; +} + +/** + * radix_tree_lookup_slot - lookup a slot in a radix tree + * @root: radix tree root + * @index: index key + * + * Lookup the slot corresponding to the position @index in the radix tree + * @root. This is useful for update-if-exists operations. + */ +void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) +{ + return __lookup_slot(root, index); +} +EXPORT_SYMBOL(radix_tree_lookup_slot); + +/** + * radix_tree_lookup - perform lookup operation on a radix tree + * @root: radix tree root + * @index: index key + * + * Lookup the item at the position @index in the radix tree @root. + */ +void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) +{ + void **slot; + + slot = __lookup_slot(root, index); + return slot != NULL ? *slot : NULL; } EXPORT_SYMBOL(radix_tree_lookup); -- cgit v1.2.3 From 28ef35845f2c8da8e1bed068277d2fab1e8c8979 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 7 Nov 2005 00:59:29 -0800 Subject: [PATCH] small kernel_stat.h cleanup cleanup: use for_each_cpu() instead of an open-coded NR_CPUS loop. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kernel_stat.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index dba27749b428..a484572c302e 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -6,6 +6,7 @@ #include #include #include +#include #include /* @@ -43,11 +44,10 @@ extern unsigned long long nr_context_switches(void); */ static inline int kstat_irqs(int irq) { - int i, sum=0; + int cpu, sum = 0; - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) - sum += kstat_cpu(i).irqs[irq]; + for_each_cpu(cpu) + sum += kstat_cpu(cpu).irqs[irq]; return sum; } -- cgit v1.2.3 From d55b5fdaf40846221d543937b786956e27837fda Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 7 Nov 2005 00:59:31 -0800 Subject: [PATCH] aio: remove aio_max_nr accounting race AIO was adding a new context's max requests to the global total before testing if that resulting total was over the global limit. This let innocent tasks get their new limit tested along with a racing guilty task that was crossing the limit. This serializes the _nr accounting with a spinlock It also switches to using unsigned long for the global totals. Individual contexts are still limited to an unsigned int's worth of requests by the syscall interface. The problem and fix were verified with a simple program that spun creating and destroying a context while holding on to another long lived context. Before the patch a task creating a tiny context could get a spurious EAGAIN if it raced with a task creating a very large context that overran the limit. Signed-off-by: Zach Brown Cc: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 31 +++++++++++++++++++++---------- include/linux/aio.h | 5 +++-- kernel/sysctl.c | 4 ++-- 3 files changed, 26 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/fs/aio.c b/fs/aio.c index edfca5b75535..20bb919eb195 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -42,8 +42,9 @@ #endif /*------ sysctl variables----*/ -atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ -unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ +static DEFINE_SPINLOCK(aio_nr_lock); +unsigned long aio_nr; /* current system wide number of aio requests */ +unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ /*----end sysctl variables---*/ static kmem_cache_t *kiocb_cachep; @@ -208,7 +209,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ERR_PTR(-EINVAL); } - if (nr_events > aio_max_nr) + if ((unsigned long)nr_events > aio_max_nr) return ERR_PTR(-EAGAIN); ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL); @@ -233,8 +234,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) goto out_freectx; /* limit the number of system wide aios */ - atomic_add(ctx->max_reqs, &aio_nr); /* undone by __put_ioctx */ - if (unlikely(atomic_read(&aio_nr) > aio_max_nr)) + spin_lock(&aio_nr_lock); + if (aio_nr + ctx->max_reqs > aio_max_nr || + aio_nr + ctx->max_reqs < aio_nr) + ctx->max_reqs = 0; + else + aio_nr += ctx->max_reqs; + spin_unlock(&aio_nr_lock); + if (ctx->max_reqs == 0) goto out_cleanup; /* now link into global list. kludge. FIXME */ @@ -248,8 +255,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ctx; out_cleanup: - atomic_sub(ctx->max_reqs, &aio_nr); - ctx->max_reqs = 0; /* prevent __put_ioctx from sub'ing aio_nr */ __put_ioctx(ctx); return ERR_PTR(-EAGAIN); @@ -374,7 +379,12 @@ void fastcall __put_ioctx(struct kioctx *ctx) pr_debug("__put_ioctx: freeing %p\n", ctx); kmem_cache_free(kioctx_cachep, ctx); - atomic_sub(nr_events, &aio_nr); + if (nr_events) { + spin_lock(&aio_nr_lock); + BUG_ON(aio_nr - nr_events > aio_nr); + aio_nr -= nr_events; + spin_unlock(&aio_nr_lock); + } } /* aio_get_req @@ -1258,8 +1268,9 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) goto out; ret = -EINVAL; - if (unlikely(ctx || (int)nr_events <= 0)) { - pr_debug("EINVAL: io_setup: ctx or nr_events > max\n"); + if (unlikely(ctx || nr_events == 0)) { + pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n", + ctx, nr_events); goto out; } diff --git a/include/linux/aio.h b/include/linux/aio.h index 0decf66117c1..403d71dcb7c8 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -183,6 +183,7 @@ struct kioctx { struct list_head active_reqs; /* used for cancellation */ struct list_head run_list; /* used for kicked reqs */ + /* sys_io_setup currently limits this to an unsigned int */ unsigned max_reqs; struct aio_ring_info ring_info; @@ -234,7 +235,7 @@ static inline struct kiocb *list_kiocb(struct list_head *h) } /* for sysctl: */ -extern atomic_t aio_nr; -extern unsigned aio_max_nr; +extern unsigned long aio_nr; +extern unsigned long aio_max_nr; #endif /* __LINUX__AIO_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8e56e2495542..e1351200ce85 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -952,7 +952,7 @@ static ctl_table fs_table[] = { .data = &aio_nr, .maxlen = sizeof(aio_nr), .mode = 0444, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, { .ctl_name = FS_AIO_MAX_NR, @@ -960,7 +960,7 @@ static ctl_table fs_table[] = { .data = &aio_max_nr, .maxlen = sizeof(aio_max_nr), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, #ifdef CONFIG_INOTIFY { -- cgit v1.2.3 From be586bab8bfbf5d429bdfcb6136bdde89583c5c4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:59:35 -0800 Subject: [PATCH] quota: small cleanups - "extern inline" -> "static inline" - every file should #include the headers containing the prototypes for it's global functions Signed-off-by: Adrian Bunk Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dquot.c | 1 + fs/quota.c | 1 + include/linux/quotaops.h | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fs/dquot.c b/fs/dquot.c index ea7644227a65..afa06a893468 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -77,6 +77,7 @@ #include #include #include +#include #include diff --git a/fs/quota.c b/fs/quota.c index 1df7832b4e08..612e04db4b93 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -15,6 +15,7 @@ #include #include #include +#include /* Check validity of generic quotactl commands */ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d211507ab246..4f34d3d60f2e 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -198,38 +198,38 @@ static __inline__ int DQUOT_OFF(struct super_block *sb) #define DQUOT_SYNC(sb) do { } while(0) #define DQUOT_OFF(sb) do { } while(0) #define DQUOT_TRANSFER(inode, iattr) (0) -extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_add_bytes(inode, nr); return 0; } -extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) +static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) { DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_add_bytes(inode, nr); return 0; } -extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) +static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) { DQUOT_ALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); } -extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) +static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) { DQUOT_FREE_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); -- cgit v1.2.3 From 8c65b4a60450590e79a28e9717ceffa9e4debb3f Mon Sep 17 00:00:00 2001 From: Tim Schmielau Date: Mon, 7 Nov 2005 00:59:43 -0800 Subject: [PATCH] fix remaining missing includes Fix more include file problems that surfaced since I submitted the previous fix-missing-includes.patch. This should now allow not to include sched.h from module.h, which is done by a followup patch. Signed-off-by: Tim Schmielau Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-aaec2000/clock.c | 1 + arch/arm/mach-epxa10db/mm.c | 1 + arch/arm/mach-pxa/corgi_lcd.c | 1 + arch/ppc/syslib/ppc_sys.c | 1 + drivers/base/power/sysfs.c | 1 + drivers/char/agp/amd64-agp.c | 1 + drivers/hwmon/hwmon.c | 1 + drivers/infiniband/core/agent.c | 3 +++ drivers/infiniband/core/packer.c | 2 ++ drivers/infiniband/core/sysfs.c | 3 +++ drivers/infiniband/core/ud_header.c | 1 + drivers/infiniband/core/verbs.c | 1 + drivers/infiniband/hw/mthca/mthca_catas.c | 3 +++ drivers/infiniband/hw/mthca/mthca_srq.c | 3 +++ drivers/media/dvb/frontends/cx24110.c | 1 + drivers/message/i2o/exec-osm.c | 1 + drivers/mfd/mcp-core.c | 2 ++ drivers/pci/hotplug/pciehprm_nonacpi.c | 1 + drivers/pci/pci-driver.c | 1 + drivers/scsi/atari_dma_emul.c | 2 ++ drivers/scsi/raid_class.c | 2 ++ drivers/scsi/scsi_transport_sas.c | 2 ++ drivers/scsi/sym53c8xx_2/sym_hipd.c | 1 + fs/9p/error.c | 1 + include/asm-alpha/pgtable.h | 3 +++ include/asm-cris/processor.h | 2 ++ include/asm-frv/pgtable.h | 2 ++ include/asm-generic/pgtable.h | 1 + include/asm-i386/elf.h | 2 ++ include/asm-i386/pgtable.h | 3 +++ include/asm-ia64/pgtable.h | 1 + include/asm-m32r/pgtable.h | 3 +++ include/asm-mips/elf.h | 2 ++ include/asm-mips/pgtable.h | 3 +++ include/asm-parisc/pgtable.h | 3 ++- include/asm-powerpc/elf.h | 2 ++ include/asm-ppc/pgtable.h | 1 + include/asm-ppc64/pgtable.h | 1 + include/asm-s390/elf.h | 1 + include/asm-s390/pgtable.h | 1 + include/asm-sh/elf.h | 1 + include/asm-sh/pgtable.h | 2 ++ include/asm-sh64/pgtable.h | 2 ++ include/asm-x86_64/elf.h | 2 ++ include/asm-x86_64/pgtable.h | 2 ++ include/asm-xtensa/elf.h | 2 ++ include/asm-xtensa/pgtable.h | 3 +++ include/linux/irq.h | 1 + include/linux/memory.h | 3 +++ include/linux/sem.h | 2 ++ include/linux/wait.h | 1 + kernel/module.c | 1 + 52 files changed, 89 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c index 99e019169dda..0340ddc4824e 100644 --- a/arch/arm/mach-aaec2000/clock.c +++ b/arch/arm/mach-aaec2000/clock.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c index e8832d0910ee..cfd0d2182d44 100644 --- a/arch/arm/mach-epxa10db/mm.c +++ b/arch/arm/mach-epxa10db/mm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c index 54162ba95414..698eb06545c4 100644 --- a/arch/arm/mach-pxa/corgi_lcd.c +++ b/arch/arm/mach-pxa/corgi_lcd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 62ee86e80711..603f01190816 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -14,6 +14,7 @@ * option) any later version. */ +#include #include int (*ppc_sys_device_fixup) (struct platform_device * pdev); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 89c57875f3e5..f3a0c562bcb5 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -3,6 +3,7 @@ */ #include +#include #include "power.h" diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 0e6c3a31d344..78ce98a69f37 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /* PAGE_SIZE */ #include "agp.h" diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 6f48579799b5..dddd3eb9b387 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -16,6 +16,7 @@ #include #include #include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index 7545775d38ef..34b724afd28d 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -37,6 +37,9 @@ * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $ */ +#include +#include + #include "agent.h" #include "smi.h" diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c index 35df5010e723..c972d7235764 100644 --- a/drivers/infiniband/core/packer.c +++ b/drivers/infiniband/core/packer.c @@ -33,6 +33,8 @@ * $Id: packer.c 1349 2004-12-16 21:09:43Z roland $ */ +#include + #include static u64 value_read(int offset, int size, void *structure) diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index b8120650e711..08648b1a387e 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -36,6 +36,9 @@ #include "core_priv.h" +#include +#include + #include struct ib_port { diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c index 527b23450ab3..997c07db6d8f 100644 --- a/drivers/infiniband/core/ud_header.c +++ b/drivers/infiniband/core/ud_header.c @@ -34,6 +34,7 @@ */ #include +#include #include diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 72d3ef786db5..4186cc888ea5 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -40,6 +40,7 @@ #include #include +#include #include #include diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index 7ac52af43b99..25ebab64bc42 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c @@ -32,6 +32,9 @@ * $Id$ */ +#include +#include + #include "mthca_dev.h" enum { diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 292f55be8cbd..26d5161fde07 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -32,6 +32,9 @@ * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $ */ +#include +#include + #include "mthca_dev.h" #include "mthca_cmd.h" #include "mthca_memfree.h" diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index d4b97989e3ed..654d7dc879d9 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "cx24110.h" diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index b675b4ebbebd..9c339a2505b0 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -33,6 +33,7 @@ #include #include #include +#include /* wait_event_interruptible_timeout() needs this */ #include /* HZ */ #include "core.h" diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index c75d713c01e4..55ba23075c90 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 33b2c69a0829..76c727c74cc0 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index ae986e590b48..94e68c54d273 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pci.h" /* diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c index 7026045527fd..8d5d2a5da961 100644 --- a/drivers/scsi/atari_dma_emul.c +++ b/drivers/scsi/atari_dma_emul.c @@ -19,6 +19,8 @@ * this code. */ +#include +#include #include #define hades_dma_ctrl (*(unsigned char *) 0xffff8717) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index f1ea5027865f..caa0c3629626 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 0cc766a9aa65..edabbd05d258 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a1a58e1d5ad3..a7420cad4547 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -39,6 +39,7 @@ */ #include +#include /* for timeouts in units of HZ */ #include "sym_glue.h" #include "sym_nvram.h" diff --git a/fs/9p/error.c b/fs/9p/error.c index fee5d19179c5..834cb179e388 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c @@ -33,6 +33,7 @@ #include #include +#include #include "debug.h" #include "error.h" diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 8393bf374b2b..a985cd29b6db 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -17,6 +17,9 @@ #include /* For TASK_SIZE */ #include +struct mm_struct; +struct vm_area_struct; + /* Certain architectures need to do special things when PTEs * within a page table are directly modified. Thus, the following * hook is made available. diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h index e8b2abb2ae59..dce41009eeb0 100644 --- a/include/asm-cris/processor.h +++ b/include/asm-cris/processor.h @@ -16,6 +16,8 @@ #include #include +struct task_struct; + /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h index b247e99dff49..844666377dcb 100644 --- a/include/asm-frv/pgtable.h +++ b/include/asm-frv/pgtable.h @@ -26,6 +26,8 @@ #include #include #include +struct mm_struct; +struct vm_area_struct; #endif #ifndef __ASSEMBLY__ diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 7dca30a26c53..358e4d309ceb 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -128,6 +128,7 @@ do { \ #endif #ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT +struct mm_struct; static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) { pte_t old_pte = *ptep; diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h index fa11117d3cfa..4153d80e4d2b 100644 --- a/include/asm-i386/elf.h +++ b/include/asm-i386/elf.h @@ -119,6 +119,8 @@ typedef struct user_fxsr_struct elf_fpxregset_t; */ #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) +struct task_struct; + extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct *); diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 03f3c8ac6383..088a945bf26b 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -25,6 +25,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + /* * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 21e32a06bc82..c34ba80c1c31 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -127,6 +127,7 @@ # ifndef __ASSEMBLY__ +#include /* for mm_struct */ #include #include #include diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h index 1cd5fd4a5b2c..75740debcd01 100644 --- a/include/asm-m32r/pgtable.h +++ b/include/asm-m32r/pgtable.h @@ -27,6 +27,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + extern pgd_t swapper_pg_dir[1024]; extern void paging_init(void); diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h index 7420f12742bb..d2c9a25f8459 100644 --- a/include/asm-mips/elf.h +++ b/include/asm-mips/elf.h @@ -275,6 +275,8 @@ do { \ #endif /* CONFIG_64BIT */ +struct task_struct; + extern void dump_regs(elf_greg_t *, struct pt_regs *regs); extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 34facd996503..702a28fa7a34 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -19,6 +19,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ PAGE_CACHABLE_DEFAULT) diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index c28fb6f48c6c..b4554711c3e7 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -12,6 +12,7 @@ */ #include +#include /* for vm_area_struct */ #include #include #include @@ -418,7 +419,6 @@ extern void paging_init (void); #define PG_dcache_dirty PG_arch_1 -struct vm_area_struct; /* forward declaration (include/linux/mm.h) */ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ @@ -464,6 +464,7 @@ static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned extern spinlock_t pa_dbit_lock; +struct mm_struct; static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t old_pte; diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index d140577d0a05..feac3458d71f 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -1,11 +1,13 @@ #ifndef _ASM_POWERPC_ELF_H #define _ASM_POWERPC_ELF_H +#include /* for task_struct */ #include #include #include #include #include +#include /* PowerPC relocations defined by the ABIs */ #define R_PPC_NONE 0 diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index b28a713ba862..6d1c39e8a6af 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -12,6 +12,7 @@ #include /* For TASK_SIZE */ #include #include +struct mm_struct; extern unsigned long va_to_phys(unsigned long address); extern pte_t *va_to_pte(unsigned long address); diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index fde93ec36abc..a9783ba7fe98 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -13,6 +13,7 @@ #include #include #include +struct mm_struct; #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PPC_64K_PAGES diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h index 3b8bd46832a1..372d51cccd53 100644 --- a/include/asm-s390/elf.h +++ b/include/asm-s390/elf.h @@ -96,6 +96,7 @@ * ELF register definitions.. */ +#include /* for task_struct */ #include #include #include /* for save_access_regs */ diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index df94f89038cc..9be741bb1496 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -36,6 +36,7 @@ #include struct vm_area_struct; /* forward declaration (include/linux/mm.h) */ +struct mm_struct; extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); extern void paging_init(void); diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h index 8fe00a1981ce..1b63dfeea4f2 100644 --- a/include/asm-sh/elf.h +++ b/include/asm-sh/elf.h @@ -111,6 +111,7 @@ typedef struct user_fpu_struct elf_fpregset_t; #ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) +struct task_struct; extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index dee36bcbcf98..bb0efb31a8cb 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -284,6 +284,8 @@ typedef pte_t *pte_addr_t; #define GET_IOSPACE(pfn) 0 #define GET_PFN(pfn) (pfn) +struct mm_struct; + /* * No page table caches to initialise */ diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h index 51b05818e4eb..a1906a772df9 100644 --- a/include/asm-sh64/pgtable.h +++ b/include/asm-sh64/pgtable.h @@ -24,6 +24,8 @@ #include #include +struct vm_area_struct; + extern void paging_init(void); /* We provide our own get_unmapped_area to avoid cache synonym issue */ diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h index a60a35e79222..43862cd6a569 100644 --- a/include/asm-x86_64/elf.h +++ b/include/asm-x86_64/elf.h @@ -149,6 +149,8 @@ extern void set_personality_64bit(void); */ #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) +struct task_struct; + extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 7a07196a7202..7309fffeec9a 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -105,6 +105,8 @@ static inline void pgd_clear (pgd_t * pgd) #define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0)) +struct mm_struct; + static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full) { pte_t pte; diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h index 64f1f53874fe..de0667453b2e 100644 --- a/include/asm-xtensa/elf.h +++ b/include/asm-xtensa/elf.h @@ -209,6 +209,8 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *); #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) +struct task_struct; + extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*, struct task_struct*); extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*, diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h index 987e3b802313..7b15afb70c56 100644 --- a/include/asm-xtensa/pgtable.h +++ b/include/asm-xtensa/pgtable.h @@ -278,6 +278,8 @@ static inline void update_pte(pte_t *ptep, pte_t pteval) #endif } +struct mm_struct; + static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { @@ -294,6 +296,7 @@ set_pmd(pmd_t *pmdp, pmd_t pmdval) #endif } +struct vm_area_struct; static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, diff --git a/include/linux/irq.h b/include/linux/irq.h index 69681c3b1f05..c516382fbec2 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -10,6 +10,7 @@ */ #include +#include /* cpu_online_map */ #if !defined(CONFIG_ARCH_S390) diff --git a/include/linux/memory.h b/include/linux/memory.h index 0def328ab5cf..9a424383e6c6 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -54,6 +54,9 @@ struct memory_block { */ #define MEM_MAPPING_INVALID (1<<3) +struct notifier_block; +struct mem_section; + #ifndef CONFIG_MEMORY_HOTPLUG static inline int memory_dev_init(void) { diff --git a/include/linux/sem.h b/include/linux/sem.h index 106f9757339a..3c1f1120fe88 100644 --- a/include/linux/sem.h +++ b/include/linux/sem.h @@ -79,6 +79,8 @@ struct seminfo { #ifdef __KERNEL__ +struct task_struct; + /* One semaphore structure for each semaphore in the system. */ struct sem { int semval; /* current value */ diff --git a/include/linux/wait.h b/include/linux/wait.h index d38c9fecdc36..d28518236b62 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -54,6 +54,7 @@ struct __wait_queue_head { }; typedef struct __wait_queue_head wait_queue_head_t; +struct task_struct; /* * Macros for declaration and initialisaton of the datatypes diff --git a/kernel/module.c b/kernel/module.c index ff5c500ab625..2ea929d51ad0 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 481bed454247538e9f57d4ea37b153ccba24ba7b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:47 -0800 Subject: [PATCH] consolidate sys_ptrace() The sys_ptrace boilerplate code (everything outside the big switch statement for the arch-specific requests) is shared by most architectures. This patch moves it to kernel/ptrace.c and leaves the arch-specific code as arch_ptrace. Some architectures have a too different ptrace so we have to exclude them. They continue to keep their implementations. For sh64 I had to add a sh64_ptrace wrapper because it does some initialization on the first call. For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree. Signed-off-by: Christoph Hellwig Acked-by: Paul Mackerras Acked-by: Ralf Baechle Acked-By: David Howells Acked-by: Russell King Acked-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/kernel/ptrace.c | 49 +--------------------- arch/arm26/kernel/ptrace.c | 49 +--------------------- arch/cris/arch-v10/kernel/ptrace.c | 51 +---------------------- arch/cris/arch-v32/kernel/ptrace.c | 51 +---------------------- arch/frv/kernel/ptrace.c | 43 +------------------- arch/h8300/kernel/ptrace.c | 39 +----------------- arch/i386/kernel/ptrace.c | 44 +------------------- arch/m68k/kernel/ptrace.c | 47 ++------------------- arch/m68knommu/kernel/ptrace.c | 39 +----------------- arch/mips/kernel/ptrace.c | 55 +++---------------------- arch/parisc/kernel/ptrace.c | 50 ++--------------------- arch/powerpc/kernel/ptrace.c | 43 +------------------- arch/sh/kernel/ptrace.c | 44 +------------------- arch/sh64/kernel/ptrace.c | 83 +++++++++++++------------------------- arch/sh64/kernel/syscalls.S | 2 +- arch/um/kernel/ptrace.c | 50 +---------------------- arch/v850/kernel/ptrace.c | 43 +------------------- arch/x86_64/kernel/ptrace.c | 43 +------------------- arch/xtensa/kernel/ptrace.c | 55 +------------------------ include/asm-alpha/ptrace.h | 3 ++ include/asm-ia64/ptrace.h | 3 ++ include/asm-m32r/ptrace.h | 3 ++ include/asm-s390/ptrace.h | 2 + include/asm-sparc/ptrace.h | 3 ++ include/asm-sparc64/ptrace.h | 3 ++ include/linux/ptrace.h | 2 + kernel/ptrace.c | 82 +++++++++++++++++++++++++++++++++++++ 27 files changed, 163 insertions(+), 818 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 9bd8609a2926..9a340e790da5 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) #endif -static int do_ptrace(int request, struct task_struct *child, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long tmp; int ret; @@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index cf7e977d18c8..4e6b7356a722 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) sizeof(struct user_fp)) ? -EFAULT : 0; } -static int do_ptrace(int request, struct task_struct *child, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long tmp; int ret; @@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 130dd214e41d..6cbd34a27b90 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child) * (in user space) where the result of the ptrace call is written (instead of * being returned). */ -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - - if (child) - get_task_struct(child); - - read_unlock(&tasklist_lock); - - if (!child) - goto out; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: @@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 208489da2a87..5528b83a622b 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child) } -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - - if (child) - get_task_struct(child); - - read_unlock(&tasklist_lock); - - if (!child) - goto out; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: @@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index cb335a14a315..f953484e7d59 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child) child->thread.frame0->__status |= REG__STATUS_STEP; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index a569fe4aa284..0ff6f79b0fed 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child) h8300_disable_trace(child); } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index efd11f09c996..5ffbb4b7ad05 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child, return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; struct user * dummy = NULL; int i, ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out_tsk: return ret; } diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index f7f1d2e5b90b..7e54422685cf 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child) child->thread.work.syscall_trace = 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; int i, ret = 0; - lock_kernel(); - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - ret = -EPERM; - goto out; - } - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - goto out; - } - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (unlikely(!child)) { - ret = -ESRCH; - goto out; - } - - /* you may not mess with init */ - if (unlikely(pid == 1)) { - ret = -EPERM; - goto out_tsk; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; out_eio: - ret = -EIO; - goto out_tsk; + return -EIO; } asmlinkage void syscall_trace(void) diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 621d7b91ccfe..262ab8c72e5f 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child) put_reg(child, PT_SR, tmp); } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(truct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -357,10 +324,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index f1b0f3e1f95b..510da5fda567 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - if ((ret = security_ptrace(current->parent, current))) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } if (child->thread.dsp.used_dsp) { dregs = __get_dsp_regs(child); @@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } tmp = child->thread.dsp.dspcontrol; break; default: tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } ret = put_user(tmp, (unsigned long __user *) data); break; @@ -495,11 +454,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return ret; } diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 18130c3748f3..b6fe202a620d 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child) pa_psw(child)->l = 0; } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long ret; #ifdef DEBUG_PTRACE long oaddr=addr, odata=data; #endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - ret = -EPERM; - if (pid == 1) /* no messing around with init! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned int __user *) data); - goto out_tsk; + goto out; default: ret = ptrace_request(child, request, addr, data); - goto out_tsk; + goto out; } out_wake_notrap: @@ -396,10 +357,7 @@ out_wake: wake_up_process(child); ret = 0; out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", + DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n", request, pid, oaddr, odata, ret); return ret; } diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 568ea335d616..3d2abd95c7ae 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child) clear_single_step(child); } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret = -EPERM; - lock_kernel(); - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -540,10 +504,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1fbe5a428e31..1a8be06519ec 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; struct user * dummy = NULL; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -289,10 +252,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 71f2eec00b99..cd22e9471316 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; - extern void poke_real_address_q(unsigned long long addr, unsigned long long data); -#define WPC_DBRMODE 0x0d104008 - static int first_call = 1; int ret; - lock_kernel(); - - if (first_call) { - /* Set WPC.DBRMODE to 0. This makes all debug events get - * delivered through RESVEC, i.e. into the handlers in entry.S. - * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE - * would normally be left set to 1, which makes debug events get - * delivered through DBRVEC, i.e. into the remote gdb's - * handlers. This prevents ptrace getting them, and confuses - * the remote gdb.) */ - printk("DBRMODE set to 0 to permit native debugging\n"); - poke_real_address_q(WPC_DBRMODE, 0); - first_call = 0; - } - - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -313,13 +264,33 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } +asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) +{ + extern void poke_real_address_q(unsigned long long addr, unsigned long long data); +#define WPC_DBRMODE 0x0d104008 + static int first_call = 1; + + lock_kernel(); + if (first_call) { + /* Set WPC.DBRMODE to 0. This makes all debug events get + * delivered through RESVEC, i.e. into the handlers in entry.S. + * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE + * would normally be left set to 1, which makes debug events get + * delivered through DBRVEC, i.e. into the remote gdb's + * handlers. This prevents ptrace getting them, and confuses + * the remote gdb.) */ + printk("DBRMODE set to 0 to permit native debugging\n"); + poke_real_address_q(WPC_DBRMODE, 0); + first_call = 0; + } + unlock_kernel(); + + return sys_ptrace(request, pid, addr, data); +} + asmlinkage void syscall_trace(void) { struct task_struct *tsk = current; diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S index a3d037805f1c..c0079d54c850 100644 --- a/arch/sh64/kernel/syscalls.S +++ b/arch/sh64/kernel/syscalls.S @@ -46,7 +46,7 @@ sys_call_table: .long sys_setuid16 .long sys_getuid16 .long sys_stime /* 25 */ - .long sys_ptrace + .long sh64_ptrace .long sys_alarm .long sys_fstat .long sys_pause diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 71af4d503899..98e09395c093 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child) extern int peek_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data); -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int i, ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - -#ifdef SUBACH_PTRACE_SPECIAL - SUBARCH_PTRACE_SPECIAL(child,request,addr,data); -#endif - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - out_tsk: - put_task_struct(child); - out: - unlock_kernel(); + return ret; } diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index d6077ff47d22..18492d02aaf6 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val) return 1; } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int rval; - lock_kernel(); - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - rval = -EPERM; - goto out; - } - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - rval = 0; - goto out; - } - rval = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - rval = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - rval = ptrace_attach(child); - goto out_tsk; - } - rval = ptrace_check_attach(child, request == PTRACE_KILL); - if (rval < 0) - goto out_tsk; - switch (request) { unsigned long val, copied; @@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data) rval = -EIO; goto out; } - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return rval; } diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index bbf64b59a21e..a87b6cebe80f 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno) } -asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long i, ret; unsigned ui; - /* This lock_kernel fixes a subtle race with suid exec */ - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 14460743de07..ab5c4c65b5c4 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret = -EPERM; - lock_kernel(); - -#if 0 - if ((int)request != 1) - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - - if (request == PTRACE_TRACEME) { - - /* Are we already being traced? */ - - if (current->ptrace & PT_PTRACED) - goto out; - - if ((ret = security_ptrace(current->parent, current))) - goto out; - - /* Set the ptrace bit in the process flags. */ - - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: @@ -375,10 +327,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); goto out; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return ret; } diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h index d462c5e14c13..072375c135b4 100644 --- a/include/asm-alpha/ptrace.h +++ b/include/asm-alpha/ptrace.h @@ -67,6 +67,9 @@ struct switch_stack { }; #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (((regs)->ps & 8) != 0) #define instruction_pointer(regs) ((regs)->pc) #define profile_pc(regs) instruction_pointer(regs) diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index a79d1a7ecc77..2c703d6e0c86 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h @@ -229,6 +229,9 @@ struct switch_stack { }; #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + /* * We use the ia64_psr(regs)->ri to determine which of the three * instructions in bundle (16 bytes) took the sample. Generate diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h index 976417126b2d..55cd7ecfde43 100644 --- a/include/asm-m32r/ptrace.h +++ b/include/asm-m32r/ptrace.h @@ -145,6 +145,9 @@ struct pt_regs { #define PTRACE_O_TRACESYSGOOD 0x00000001 #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0) #elif defined(CONFIG_ISA_M32R) diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index fc7c96edc697..a949cc077cc7 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h @@ -468,6 +468,8 @@ struct user_regs_struct }; #ifdef __KERNEL__ +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define profile_pc(regs) instruction_pointer(regs) diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index a8ecb2d6977a..714497099a42 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h @@ -60,6 +60,9 @@ struct sparc_stackf { #define STACKFRAME_SZ sizeof(struct sparc_stackf) #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (!((regs)->psr & PSR_PS)) #define instruction_pointer(regs) ((regs)->pc) unsigned long profile_pc(struct pt_regs *); diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 6194f771e9fc..7eba90c6c753 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -94,6 +94,9 @@ struct sparc_trapf { #define STACKFRAME32_SZ sizeof(struct sparc_stackf32) #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define force_successful_syscall_return() \ do { current_thread_info()->syscall_noerror = 1; \ } while (0) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index dc6f3647bfbc..b2b3dba1298d 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -78,6 +78,8 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ + +extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 863eee8bff47..5b8dd98a230e 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -406,3 +406,85 @@ int ptrace_request(struct task_struct *child, long request, return ret; } + +#ifndef __ARCH_SYS_PTRACE +static int ptrace_get_task_struct(long request, long pid, + struct task_struct **childp) +{ + struct task_struct *child; + int ret; + + /* + * Callers use child == NULL as an indication to exit early even + * when the return value is 0, so make sure it is non-NULL here. + */ + *childp = NULL; + + if (request == PTRACE_TRACEME) { + /* + * Are we already being traced? + */ + if (current->ptrace & PT_PTRACED) + return -EPERM; + ret = security_ptrace(current->parent, current); + if (ret) + return -EPERM; + /* + * Set the ptrace bit in the process ptrace flags. + */ + current->ptrace |= PT_PTRACED; + return 0; + } + + /* + * You may not mess with init + */ + if (pid == 1) + return -EPERM; + + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + return -ESRCH; + + *childp = child; + return 0; +} + +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + ret = ptrace_get_task_struct(request, pid, &child); + if (!child) + goto out; + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + goto out; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + if (ret < 0) + goto out_put_task_struct; + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* __ARCH_SYS_PTRACE */ -- cgit v1.2.3 From cc4e69dee4a080f6eae3f410daec2593f4fa6f00 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:49 -0800 Subject: [PATCH] VFS: pass file pointer to filesystem from ftruncate() This patch extends the iattr structure with a file pointer memeber, and adds an ATTR_FILE validity flag for this member. This is set if do_truncate() is invoked from ftruncate() or from do_coredump(). The change is source and binary compatible. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- fs/namei.c | 2 +- fs/open.c | 10 +++++++--- include/linux/fs.h | 10 +++++++++- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fs/exec.c b/fs/exec.c index ce76b33f25ac..cd6c574557dc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1511,7 +1511,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) goto close_fail; if (!file->f_op->write) goto close_fail; - if (do_truncate(file->f_dentry, 0) != 0) + if (do_truncate(file->f_dentry, 0, file) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file); diff --git a/fs/namei.c b/fs/namei.c index c5769c4fcab1..b3f8a1966c9c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1459,7 +1459,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0); + error = do_truncate(dentry, 0, NULL); } put_write_access(inode); if (error) diff --git a/fs/open.c b/fs/open.c index 2835f096c683..6e8136751e9a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -194,7 +194,7 @@ out: return error; } -int do_truncate(struct dentry *dentry, loff_t length) +int do_truncate(struct dentry *dentry, loff_t length, struct file *filp) { int err; struct iattr newattrs; @@ -205,6 +205,10 @@ int do_truncate(struct dentry *dentry, loff_t length) newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; + if (filp) { + newattrs.ia_file = filp; + newattrs.ia_valid |= ATTR_FILE; + } down(&dentry->d_inode->i_sem); err = notify_change(dentry, &newattrs); @@ -262,7 +266,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(nd.dentry, length); + error = do_truncate(nd.dentry, length, NULL); } put_write_access(inode); @@ -314,7 +318,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) error = locks_verify_truncate(inode, file, length); if (!error) - error = do_truncate(dentry, length); + error = do_truncate(dentry, length, file); out_putf: fput(file); out: diff --git a/include/linux/fs.h b/include/linux/fs.h index 6d6226732c93..0c89fc9481a8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -264,6 +264,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define ATTR_ATTR_FLAG 1024 #define ATTR_KILL_SUID 2048 #define ATTR_KILL_SGID 4096 +#define ATTR_FILE 8192 /* * This is the Inode Attributes structure, used for notify_change(). It @@ -283,6 +284,13 @@ struct iattr { struct timespec ia_atime; struct timespec ia_mtime; struct timespec ia_ctime; + + /* + * Not an attribute, but an auxilary info for filesystems wanting to + * implement an ftruncate() like method. NOTE: filesystem should + * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). + */ + struct file *ia_file; }; /* @@ -1288,7 +1296,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode) /* fs/open.c */ -extern int do_truncate(struct dentry *, loff_t start); +extern int do_truncate(struct dentry *, loff_t start, struct file *filp); extern long do_sys_open(const char __user *filename, int flags, int mode); extern struct file *filp_open(const char *, int, int); extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -- cgit v1.2.3 From 5b62073d502a88fedc5c369f8a004bda7c9d1999 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:49 -0800 Subject: [PATCH] FUSE: bump interface minor version Though the following changes are all backward compatible (from the kernel's as well as the library's POV) change the minor version, so interested applications can detect new features. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fuse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fuse.h b/include/linux/fuse.h index f98854c2abd7..6e91c9a3a0b6 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -14,7 +14,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 2 +#define FUSE_KERNEL_MINOR_VERSION 3 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 -- cgit v1.2.3 From 31d40d74b402a6fa18a006fb3745f64609f35b77 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:50 -0800 Subject: [PATCH] FUSE: add access call Add a new access call, which will only be called if ->permission is invoked from sys_access(). In all other cases permission checking is delayed until the actual filesystem operation. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 35 +++++++++++++++++++++++++++++++++++ fs/fuse/fuse_i.h | 3 +++ include/linux/fuse.h | 8 +++++++- 3 files changed, 45 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 61b58fdd973e..4bc1afcc476d 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry) return fuse_do_getattr(inode); } +static int fuse_access(struct inode *inode, int mask) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_req *req; + struct fuse_access_in inarg; + int err; + + if (fc->no_access) + return 0; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.mask = mask; + req->in.h.opcode = FUSE_ACCESS; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + if (err == -ENOSYS) { + fc->no_access = 1; + err = 0; + } + return err; +} + static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) { struct fuse_conn *fc = get_fuse_conn(inode); @@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) int mode = inode->i_mode; if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) return -EACCES; + + if (nd && (nd->flags & LOOKUP_ACCESS)) + return fuse_access(inode, mask); return 0; } } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5cb456f572c1..c4e8c3b47982 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -266,6 +266,9 @@ struct fuse_conn { /** Is removexattr not implemented by fs? */ unsigned no_removexattr : 1; + /** Is access not implemented by fs? */ + unsigned no_access : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 6e91c9a3a0b6..507913b65af0 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -99,7 +99,8 @@ enum fuse_opcode { FUSE_OPENDIR = 27, FUSE_READDIR = 28, FUSE_RELEASEDIR = 29, - FUSE_FSYNCDIR = 30 + FUSE_FSYNCDIR = 30, + FUSE_ACCESS = 34 }; /* Conservative buffer size for the client */ @@ -222,6 +223,11 @@ struct fuse_getxattr_out { __u32 padding; }; +struct fuse_access_in { + __u32 mask; + __u32 padding; +}; + struct fuse_init_in_out { __u32 major; __u32 minor; -- cgit v1.2.3 From fd72faac95d7e47610e981d7ed7b3c1529e55c88 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:51 -0800 Subject: [PATCH] FUSE: atomic create+open This patch adds an atomic create+open operation. This does not yet work if the file type changes between lookup and create+open, but solves the permission checking problems for the separte create and open methods. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 7 +++ fs/fuse/dir.c | 106 ++++++++++++++++++++++++++++++++++++++++- fs/fuse/file.c | 132 +++++++++++++++++++++++++++++++++------------------ fs/fuse/fuse_i.h | 14 ++++++ include/linux/fuse.h | 5 +- 5 files changed, 214 insertions(+), 50 deletions(-) (limited to 'include') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a6f90a6c754a..8f873e621f41 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -184,6 +184,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) fuse_putback_request() */ for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) up(&fc->outstanding_sem); + } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { + /* Special case for failed iget in CREATE */ + u64 nodeid = req->in.h.nodeid; + __fuse_get_request(req); + fuse_reset_request(req); + fuse_send_forget(fc, req, nodeid, 1); + putback = 0; } if (putback) fuse_putback_request(fc, req); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 4bc1afcc476d..83be119ef067 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -13,6 +13,7 @@ #include #include #include +#include static inline unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) @@ -134,6 +135,101 @@ static void fuse_invalidate_entry(struct dentry *entry) entry->d_time = jiffies - 1; } +static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, + struct nameidata *nd) +{ + int err; + struct inode *inode; + struct fuse_conn *fc = get_fuse_conn(dir); + struct fuse_req *req; + struct fuse_open_in inarg; + struct fuse_open_out outopen; + struct fuse_entry_out outentry; + struct fuse_inode *fi; + struct fuse_file *ff; + struct file *file; + int flags = nd->intent.open.flags - 1; + + err = -ENOSYS; + if (fc->no_create) + goto out; + + err = -ENAMETOOLONG; + if (entry->d_name.len > FUSE_NAME_MAX) + goto out; + + err = -EINTR; + req = fuse_get_request(fc); + if (!req) + goto out; + + ff = fuse_file_alloc(); + if (!ff) + goto out_put_request; + + flags &= ~O_NOCTTY; + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = flags; + inarg.mode = mode; + req->in.h.opcode = FUSE_CREATE; + req->in.h.nodeid = get_node_id(dir); + req->inode = dir; + req->in.numargs = 2; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->in.args[1].size = entry->d_name.len + 1; + req->in.args[1].value = entry->d_name.name; + req->out.numargs = 2; + req->out.args[0].size = sizeof(outentry); + req->out.args[0].value = &outentry; + req->out.args[1].size = sizeof(outopen); + req->out.args[1].value = &outopen; + request_send(fc, req); + err = req->out.h.error; + if (err) { + if (err == -ENOSYS) + fc->no_create = 1; + goto out_free_ff; + } + + err = -EIO; + if (!S_ISREG(outentry.attr.mode)) + goto out_free_ff; + + inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, + &outentry.attr); + err = -ENOMEM; + if (!inode) { + flags &= ~(O_CREAT | O_EXCL | O_TRUNC); + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0); + goto out_put_request; + } + fuse_put_request(fc, req); + entry->d_time = time_to_jiffies(outentry.entry_valid, + outentry.entry_valid_nsec); + fi = get_fuse_inode(inode); + fi->i_time = time_to_jiffies(outentry.attr_valid, + outentry.attr_valid_nsec); + + d_instantiate(entry, inode); + file = lookup_instantiate_filp(nd, entry, generic_file_open); + if (IS_ERR(file)) { + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0); + return PTR_ERR(file); + } + fuse_finish_open(inode, file, ff, &outopen); + return 0; + + out_free_ff: + fuse_file_free(ff); + out_put_request: + fuse_put_request(fc, req); + out: + return err; +} + static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, int mode) @@ -208,6 +304,12 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, static int fuse_create(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { + if (nd && (nd->flags & LOOKUP_CREATE)) { + int err = fuse_create_open(dir, entry, mode, nd); + if (err != -ENOSYS) + return err; + /* Fall back on mknod */ + } return fuse_mknod(dir, entry, mode, 0); } @@ -767,7 +869,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) { struct inode *inode; - int err = fuse_lookup_iget(dir, entry, &inode); + int err; + + err = fuse_lookup_iget(dir, entry, &inode); if (err) return ERR_PTR(err); if (inode && S_ISDIR(inode->i_mode)) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 657ab11c173b..2ca86141d13a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -14,11 +14,69 @@ static struct file_operations fuse_direct_io_file_operations; -int fuse_open_common(struct inode *inode, struct file *file, int isdir) +static int fuse_send_open(struct inode *inode, struct file *file, int isdir, + struct fuse_open_out *outargp) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_req *req; struct fuse_open_in inarg; + struct fuse_req *req; + int err; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->out.numargs = 1; + req->out.args[0].size = sizeof(*outargp); + req->out.args[0].value = outargp; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + + return err; +} + +struct fuse_file *fuse_file_alloc(void) +{ + struct fuse_file *ff; + ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + if (ff) { + ff->release_req = fuse_request_alloc(); + if (!ff->release_req) { + kfree(ff); + ff = NULL; + } + } + return ff; +} + +void fuse_file_free(struct fuse_file *ff) +{ + fuse_request_free(ff->release_req); + kfree(ff); +} + +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg) +{ + if (outarg->open_flags & FOPEN_DIRECT_IO) + file->f_op = &fuse_direct_io_file_operations; + if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) + invalidate_inode_pages(inode->i_mapping); + ff->fh = outarg->fh; + file->private_data = ff; +} + +int fuse_open_common(struct inode *inode, struct file *file, int isdir) +{ struct fuse_open_out outarg; struct fuse_file *ff; int err; @@ -34,73 +92,53 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) /* If opening the root node, no lookup has been performed on it, so the attributes must be refreshed */ if (get_node_id(inode) == FUSE_ROOT_ID) { - int err = fuse_do_getattr(inode); + err = fuse_do_getattr(inode); if (err) return err; } - req = fuse_get_request(fc); - if (!req) - return -EINTR; - - err = -ENOMEM; - ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + ff = fuse_file_alloc(); if (!ff) - goto out_put_request; + return -ENOMEM; - ff->release_req = fuse_request_alloc(); - if (!ff->release_req) { - kfree(ff); - goto out_put_request; - } - - memset(&inarg, 0, sizeof(inarg)); - inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; - req->in.h.nodeid = get_node_id(inode); - req->inode = inode; - req->in.numargs = 1; - req->in.args[0].size = sizeof(inarg); - req->in.args[0].value = &inarg; - req->out.numargs = 1; - req->out.args[0].size = sizeof(outarg); - req->out.args[0].value = &outarg; - request_send(fc, req); - err = req->out.h.error; - if (err) { - fuse_request_free(ff->release_req); - kfree(ff); - } else { - if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO)) - file->f_op = &fuse_direct_io_file_operations; - if (!(outarg.open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages(inode->i_mapping); - ff->fh = outarg.fh; - file->private_data = ff; + err = fuse_send_open(inode, file, isdir, &outarg); + if (err) + fuse_file_free(ff); + else { + if (isdir) + outarg.open_flags &= ~FOPEN_DIRECT_IO; + fuse_finish_open(inode, file, ff, &outarg); } - out_put_request: - fuse_put_request(fc, req); return err; } -int fuse_release_common(struct inode *inode, struct file *file, int isdir) +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir) { - struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; - struct fuse_req *req = ff->release_req; + struct fuse_req * req = ff->release_req; struct fuse_release_in *inarg = &req->misc.release_in; inarg->fh = ff->fh; - inarg->flags = file->f_flags & ~O_EXCL; + inarg->flags = flags; req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; - req->in.h.nodeid = get_node_id(inode); + req->in.h.nodeid = nodeid; req->inode = inode; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; request_send_background(fc, req); kfree(ff); +} + +int fuse_release_common(struct inode *inode, struct file *file, int isdir) +{ + struct fuse_file *ff = file->private_data; + if (ff) { + struct fuse_conn *fc = get_fuse_conn(inode); + u64 nodeid = get_node_id(inode); + fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir); + } /* Return value is ignored by VFS */ return 0; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index c4e8c3b47982..0ea5301f86be 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -269,6 +269,9 @@ struct fuse_conn { /** Is access not implemented by fs? */ unsigned no_access : 1; + /** Is create not implemented by fs? */ + unsigned no_create : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; @@ -340,6 +343,17 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, */ int fuse_open_common(struct inode *inode, struct file *file, int isdir); +struct fuse_file *fuse_file_alloc(void); +void fuse_file_free(struct fuse_file *ff); +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg); + +/** + * Send a RELEASE request + */ +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir); + /** * Send RELEASE or RELEASEDIR request */ diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 507913b65af0..45c398f08247 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -100,7 +100,8 @@ enum fuse_opcode { FUSE_READDIR = 28, FUSE_RELEASEDIR = 29, FUSE_FSYNCDIR = 30, - FUSE_ACCESS = 34 + FUSE_ACCESS = 34, + FUSE_CREATE = 35 }; /* Conservative buffer size for the client */ @@ -158,7 +159,7 @@ struct fuse_setattr_in { struct fuse_open_in { __u32 flags; - __u32 padding; + __u32 mode; }; struct fuse_open_out { -- cgit v1.2.3 From befc649c2274a1c35f0cd1e888dd83652cbb0422 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:52 -0800 Subject: [PATCH] FUSE: pass file handle in setattr This patch passes the file handle supplied in iattr to userspace, in case the ->setattr() was invoked from sys_ftruncate(). This solves the permission checking (or lack thereof) in ftruncate() for the class of filesystems served by an unprivileged userspace process. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 28 ++++++++++++++-------------- include/linux/fuse.h | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 83be119ef067..c045cc70c749 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -763,29 +763,29 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) return file ? fuse_fsync_common(file, de, datasync, 1) : 0; } -static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) { unsigned ivalid = iattr->ia_valid; - unsigned fvalid = 0; - - memset(fattr, 0, sizeof(*fattr)); if (ivalid & ATTR_MODE) - fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode; + arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; if (ivalid & ATTR_UID) - fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid; + arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; if (ivalid & ATTR_GID) - fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid; + arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; if (ivalid & ATTR_SIZE) - fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size; + arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; /* You can only _set_ these together (they may change by themselves) */ if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { - fvalid |= FATTR_ATIME | FATTR_MTIME; - fattr->atime = iattr->ia_atime.tv_sec; - fattr->mtime = iattr->ia_mtime.tv_sec; + arg->valid |= FATTR_ATIME | FATTR_MTIME; + arg->atime = iattr->ia_atime.tv_sec; + arg->mtime = iattr->ia_mtime.tv_sec; + } + if (ivalid & ATTR_FILE) { + struct fuse_file *ff = iattr->ia_file->private_data; + arg->valid |= FATTR_FH; + arg->fh = ff->fh; } - - return fvalid; } static int fuse_setattr(struct dentry *entry, struct iattr *attr) @@ -820,7 +820,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) return -EINTR; memset(&inarg, 0, sizeof(inarg)); - inarg.valid = iattr_to_fattr(attr, &inarg.attr); + iattr_to_fattr(attr, &inarg); req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 45c398f08247..b76b558b03d4 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -61,6 +61,7 @@ struct fuse_kstatfs { #define FATTR_SIZE (1 << 3) #define FATTR_ATIME (1 << 4) #define FATTR_MTIME (1 << 5) +#define FATTR_FH (1 << 6) /** * Flags returned by the OPEN request @@ -154,7 +155,20 @@ struct fuse_link_in { struct fuse_setattr_in { __u32 valid; __u32 padding; - struct fuse_attr attr; + __u64 fh; + __u64 size; + __u64 unused1; + __u64 atime; + __u64 mtime; + __u64 unused2; + __u32 atimensec; + __u32 mtimensec; + __u32 unused3; + __u32 mode; + __u32 unused4; + __u32 uid; + __u32 gid; + __u32 unused5; }; struct fuse_open_in { -- cgit v1.2.3 From 393d2cc354d150b8b4bb888a9da7db4c935e12bd Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:54 -0800 Subject: [PATCH] ipmi: use refcount in message handler This patch is rather large, but it really can't be done in smaller chunks easily and I believe it is an important change. This has been out and tested for a while in the latest IPMI driver release. There are no functional changes, just changes as necessary to convert the locking over (and a few minor style updates). The IPMI driver uses read/write locks to ensure that things exist while they are in use. This is bad from a number of points of view. This patch removes the rwlocks and uses refcounts and RCU lists to manage what the locks did. Signed-off-by: Corey Minyard Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 953 +++++++++++++++++++----------------- include/linux/ipmi.h | 5 +- 2 files changed, 499 insertions(+), 459 deletions(-) (limited to 'include') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 32fa82c78c73..320d7f035bf9 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -38,13 +38,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #define PFX "IPMI message handler: " @@ -65,10 +65,19 @@ struct proc_dir_entry *proc_ipmi_root = NULL; the max message timer. This is in milliseconds. */ #define MAX_MSG_TIMEOUT 60000 + +/* + * The main "user" data structure. + */ struct ipmi_user { struct list_head link; + /* Set to "0" when the user is destroyed. */ + int valid; + + struct kref refcount; + /* The upper layer that handles receive messages. */ struct ipmi_user_hndl *handler; void *handler_data; @@ -87,6 +96,15 @@ struct cmd_rcvr ipmi_user_t user; unsigned char netfn; unsigned char cmd; + + /* + * This is used to form a linked lised during mass deletion. + * Since this is in an RCU list, we cannot use the link above + * or change any data until the RCU period completes. So we + * use this next variable during mass deletion so we can have + * a list and don't have to wait and restart the search on + * every individual deletion of a command. */ + struct cmd_rcvr *next; }; struct seq_table @@ -150,13 +168,11 @@ struct ipmi_smi /* What interface number are we? */ int intf_num; - /* The list of upper layers that are using me. We read-lock - this when delivering messages to the upper layer to keep - the user from going away while we are processing the - message. This means that you cannot add or delete a user - from the receive callback. */ - rwlock_t users_lock; - struct list_head users; + struct kref refcount; + + /* The list of upper layers that are using me. seq_lock + * protects this. */ + struct list_head users; /* Used for wake ups at startup. */ wait_queue_head_t waitq; @@ -193,7 +209,7 @@ struct ipmi_smi /* The list of command receivers that are registered for commands on this interface. */ - rwlock_t cmd_rcvr_lock; + spinlock_t cmd_rcvrs_lock; struct list_head cmd_rcvrs; /* Events that were queues because no one was there to receive @@ -296,16 +312,17 @@ struct ipmi_smi unsigned int events; }; +/* Used to mark an interface entry that cannot be used but is not a + * free entry, either, primarily used at creation and deletion time so + * a slot doesn't get reused too quickly. */ +#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1)) +#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ + || (i == IPMI_INVALID_INTERFACE_ENTRY)) + #define MAX_IPMI_INTERFACES 4 static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; -/* Used to keep interfaces from going away while operations are - operating on interfaces. Grab read if you are not modifying the - interfaces, write if you are. */ -static DECLARE_RWSEM(interfaces_sem); - -/* Directly protects the ipmi_interfaces data structure. This is - claimed in the timer interrupt. */ +/* Directly protects the ipmi_interfaces data structure. */ static DEFINE_SPINLOCK(interfaces_lock); /* List of watchers that want to know when smi's are added and @@ -313,20 +330,73 @@ static DEFINE_SPINLOCK(interfaces_lock); static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); static DECLARE_RWSEM(smi_watchers_sem); + +static void free_recv_msg_list(struct list_head *q) +{ + struct ipmi_recv_msg *msg, *msg2; + + list_for_each_entry_safe(msg, msg2, q, link) { + list_del(&msg->link); + ipmi_free_recv_msg(msg); + } +} + +static void clean_up_interface_data(ipmi_smi_t intf) +{ + int i; + struct cmd_rcvr *rcvr, *rcvr2; + unsigned long flags; + struct list_head list; + + free_recv_msg_list(&intf->waiting_msgs); + free_recv_msg_list(&intf->waiting_events); + + /* Wholesale remove all the entries from the list in the + * interface and wait for RCU to know that none are in use. */ + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + list_add_rcu(&list, &intf->cmd_rcvrs); + list_del_rcu(&intf->cmd_rcvrs); + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + synchronize_rcu(); + + list_for_each_entry_safe(rcvr, rcvr2, &list, link) + kfree(rcvr); + + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { + if ((intf->seq_table[i].inuse) + && (intf->seq_table[i].recv_msg)) + { + ipmi_free_recv_msg(intf->seq_table[i].recv_msg); + } + } +} + +static void intf_free(struct kref *ref) +{ + ipmi_smi_t intf = container_of(ref, struct ipmi_smi, refcount); + + clean_up_interface_data(intf); + kfree(intf); +} + int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) { - int i; + int i; + unsigned long flags; - down_read(&interfaces_sem); down_write(&smi_watchers_sem); list_add(&(watcher->link), &smi_watchers); + up_write(&smi_watchers_sem); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] != NULL) { - watcher->new_smi(i); - } + ipmi_smi_t intf = ipmi_interfaces[i]; + if (IPMI_INVALID_INTERFACE(intf)) + continue; + spin_unlock_irqrestore(&interfaces_lock, flags); + watcher->new_smi(i); + spin_lock_irqsave(&interfaces_lock, flags); } - up_write(&smi_watchers_sem); - up_read(&interfaces_sem); + spin_unlock_irqrestore(&interfaces_lock, flags); return 0; } @@ -471,8 +541,8 @@ static void deliver_response(struct ipmi_recv_msg *msg) } ipmi_free_recv_msg(msg); } else { - msg->user->handler->ipmi_recv_hndl(msg, - msg->user->handler_data); + ipmi_user_t user = msg->user; + user->handler->ipmi_recv_hndl(msg, user->handler_data); } } @@ -662,15 +732,18 @@ int ipmi_create_user(unsigned int if_num, if (! new_user) return -ENOMEM; - down_read(&interfaces_sem); - if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL) - { - rv = -EINVAL; - goto out_unlock; + spin_lock_irqsave(&interfaces_lock, flags); + intf = ipmi_interfaces[if_num]; + if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { + spin_unlock_irqrestore(&interfaces_lock, flags); + return -EINVAL; } - intf = ipmi_interfaces[if_num]; + /* Note that each existing user holds a refcount to the interface. */ + kref_get(&intf->refcount); + spin_unlock_irqrestore(&interfaces_lock, flags); + kref_init(&new_user->refcount); new_user->handler = handler; new_user->handler_data = handler_data; new_user->intf = intf; @@ -678,98 +751,92 @@ int ipmi_create_user(unsigned int if_num, if (!try_module_get(intf->handlers->owner)) { rv = -ENODEV; - goto out_unlock; + goto out_err; } if (intf->handlers->inc_usecount) { rv = intf->handlers->inc_usecount(intf->send_info); if (rv) { module_put(intf->handlers->owner); - goto out_unlock; + goto out_err; } } - write_lock_irqsave(&intf->users_lock, flags); - list_add_tail(&new_user->link, &intf->users); - write_unlock_irqrestore(&intf->users_lock, flags); - - out_unlock: - if (rv) { - kfree(new_user); - } else { - *user = new_user; - } + new_user->valid = 1; + spin_lock_irqsave(&intf->seq_lock, flags); + list_add_rcu(&new_user->link, &intf->users); + spin_unlock_irqrestore(&intf->seq_lock, flags); + *user = new_user; + return 0; - up_read(&interfaces_sem); + out_err: + kfree(new_user); + kref_put(&intf->refcount, intf_free); return rv; } -static int ipmi_destroy_user_nolock(ipmi_user_t user) +static void free_user(struct kref *ref) +{ + ipmi_user_t user = container_of(ref, struct ipmi_user, refcount); + kfree(user); +} + +int ipmi_destroy_user(ipmi_user_t user) { int rv = -ENODEV; - ipmi_user_t t_user; - struct cmd_rcvr *rcvr, *rcvr2; + ipmi_smi_t intf = user->intf; int i; unsigned long flags; + struct cmd_rcvr *rcvr; + struct list_head *entry1, *entry2; + struct cmd_rcvr *rcvrs = NULL; - /* Find the user and delete them from the list. */ - list_for_each_entry(t_user, &(user->intf->users), link) { - if (t_user == user) { - list_del(&t_user->link); - rv = 0; - break; - } - } + user->valid = 1; - if (rv) { - goto out_unlock; - } + /* Remove the user from the interface's sequence table. */ + spin_lock_irqsave(&intf->seq_lock, flags); + list_del_rcu(&user->link); - /* Remove the user from the interfaces sequence table. */ - spin_lock_irqsave(&(user->intf->seq_lock), flags); for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { - if (user->intf->seq_table[i].inuse - && (user->intf->seq_table[i].recv_msg->user == user)) + if (intf->seq_table[i].inuse + && (intf->seq_table[i].recv_msg->user == user)) { - user->intf->seq_table[i].inuse = 0; + intf->seq_table[i].inuse = 0; } } - spin_unlock_irqrestore(&(user->intf->seq_lock), flags); - - /* Remove the user from the command receiver's table. */ - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); - list_for_each_entry_safe(rcvr, rcvr2, &(user->intf->cmd_rcvrs), link) { + spin_unlock_irqrestore(&intf->seq_lock, flags); + + /* + * Remove the user from the command receiver's table. First + * we build a list of everything (not using the standard link, + * since other things may be using it till we do + * synchronize_rcu()) then free everything in that list. + */ + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { + rcvr = list_entry(entry1, struct cmd_rcvr, link); if (rcvr->user == user) { - list_del(&rcvr->link); - kfree(rcvr); + list_del_rcu(&rcvr->link); + rcvr->next = rcvrs; + rcvrs = rcvr; } } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + synchronize_rcu(); + while (rcvrs) { + rcvr = rcvrs; + rcvrs = rcvr->next; + kfree(rcvr); + } - kfree(user); + module_put(intf->handlers->owner); + if (intf->handlers->dec_usecount) + intf->handlers->dec_usecount(intf->send_info); - out_unlock: + kref_put(&intf->refcount, intf_free); - return rv; -} - -int ipmi_destroy_user(ipmi_user_t user) -{ - int rv; - ipmi_smi_t intf = user->intf; - unsigned long flags; + kref_put(&user->refcount, free_user); - down_read(&interfaces_sem); - write_lock_irqsave(&intf->users_lock, flags); - rv = ipmi_destroy_user_nolock(user); - if (!rv) { - module_put(intf->handlers->owner); - if (intf->handlers->dec_usecount) - intf->handlers->dec_usecount(intf->send_info); - } - - write_unlock_irqrestore(&intf->users_lock, flags); - up_read(&interfaces_sem); return rv; } @@ -823,62 +890,78 @@ int ipmi_get_my_LUN(ipmi_user_t user, int ipmi_set_gets_events(ipmi_user_t user, int val) { - unsigned long flags; - struct ipmi_recv_msg *msg, *msg2; + unsigned long flags; + ipmi_smi_t intf = user->intf; + struct ipmi_recv_msg *msg, *msg2; + struct list_head msgs; - read_lock(&(user->intf->users_lock)); - spin_lock_irqsave(&(user->intf->events_lock), flags); + INIT_LIST_HEAD(&msgs); + + spin_lock_irqsave(&intf->events_lock, flags); user->gets_events = val; if (val) { /* Deliver any queued events. */ - list_for_each_entry_safe(msg, msg2, &(user->intf->waiting_events), link) { + list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { list_del(&msg->link); - msg->user = user; - deliver_response(msg); + list_add_tail(&msg->link, &msgs); } } - - spin_unlock_irqrestore(&(user->intf->events_lock), flags); - read_unlock(&(user->intf->users_lock)); + + /* Hold the events lock while doing this to preserve order. */ + list_for_each_entry_safe(msg, msg2, &msgs, link) { + msg->user = user; + kref_get(&user->refcount); + deliver_response(msg); + } + + spin_unlock_irqrestore(&intf->events_lock, flags); return 0; } +static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf, + unsigned char netfn, + unsigned char cmd) +{ + struct cmd_rcvr *rcvr; + + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { + if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) + return rcvr; + } + return NULL; +} + int ipmi_register_for_cmd(ipmi_user_t user, unsigned char netfn, unsigned char cmd) { - struct cmd_rcvr *cmp; - unsigned long flags; - struct cmd_rcvr *rcvr; - int rv = 0; + ipmi_smi_t intf = user->intf; + struct cmd_rcvr *rcvr; + struct cmd_rcvr *entry; + int rv = 0; rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); if (! rcvr) return -ENOMEM; + rcvr->cmd = cmd; + rcvr->netfn = netfn; + rcvr->user = user; - read_lock(&(user->intf->users_lock)); - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); + spin_lock_irq(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ - list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { - if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { - rv = -EBUSY; - break; - } - } - - if (! rv) { - rcvr->cmd = cmd; - rcvr->netfn = netfn; - rcvr->user = user; - list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); + entry = find_cmd_rcvr(intf, netfn, cmd); + if (entry) { + rv = -EBUSY; + goto out_unlock; } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); - read_unlock(&(user->intf->users_lock)); + list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); + out_unlock: + spin_unlock_irq(&intf->cmd_rcvrs_lock); if (rv) kfree(rcvr); @@ -889,31 +972,28 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, unsigned char netfn, unsigned char cmd) { - unsigned long flags; - struct cmd_rcvr *rcvr; - int rv = -ENOENT; + ipmi_smi_t intf = user->intf; + struct cmd_rcvr *rcvr; - read_lock(&(user->intf->users_lock)); - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); + spin_lock_irq(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ - list_for_each_entry(rcvr, &(user->intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - rv = 0; - list_del(&rcvr->link); - kfree(rcvr); - break; - } + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if ((rcvr) && (rcvr->user == user)) { + list_del_rcu(&rcvr->link); + spin_unlock_irq(&intf->cmd_rcvrs_lock); + synchronize_rcu(); + kfree(rcvr); + return 0; + } else { + spin_unlock_irq(&intf->cmd_rcvrs_lock); + return -ENOENT; } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); - read_unlock(&(user->intf->users_lock)); - - return rv; } void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) { - user->intf->handlers->set_run_to_completion(user->intf->send_info, - val); + ipmi_smi_t intf = user->intf; + intf->handlers->set_run_to_completion(intf->send_info, val); } static unsigned char @@ -1010,19 +1090,19 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg, supplied in certain circumstances (mainly at panic time). If messages are supplied, they will be freed, even if an error occurs. */ -static inline int i_ipmi_request(ipmi_user_t user, - ipmi_smi_t intf, - struct ipmi_addr *addr, - long msgid, - struct kernel_ipmi_msg *msg, - void *user_msg_data, - void *supplied_smi, - struct ipmi_recv_msg *supplied_recv, - int priority, - unsigned char source_address, - unsigned char source_lun, - int retries, - unsigned int retry_time_ms) +static int i_ipmi_request(ipmi_user_t user, + ipmi_smi_t intf, + struct ipmi_addr *addr, + long msgid, + struct kernel_ipmi_msg *msg, + void *user_msg_data, + void *supplied_smi, + struct ipmi_recv_msg *supplied_recv, + int priority, + unsigned char source_address, + unsigned char source_lun, + int retries, + unsigned int retry_time_ms) { int rv = 0; struct ipmi_smi_msg *smi_msg; @@ -1051,6 +1131,8 @@ static inline int i_ipmi_request(ipmi_user_t user, } recv_msg->user = user; + if (user) + kref_get(&user->refcount); recv_msg->msgid = msgid; /* Store the message to send in the receive message so timeout responses can get the proper response data. */ @@ -1725,11 +1807,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, unsigned char version_major, unsigned char version_minor, unsigned char slave_addr, - ipmi_smi_t *intf) + ipmi_smi_t *new_intf) { int i, j; int rv; - ipmi_smi_t new_intf; + ipmi_smi_t intf; unsigned long flags; @@ -1745,189 +1827,142 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, return -ENODEV; } - new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL); - if (!new_intf) + intf = kmalloc(sizeof(*intf), GFP_KERNEL); + if (!intf) return -ENOMEM; - memset(new_intf, 0, sizeof(*new_intf)); - - new_intf->proc_dir = NULL; + memset(intf, 0, sizeof(*intf)); + intf->intf_num = -1; + kref_init(&intf->refcount); + intf->version_major = version_major; + intf->version_minor = version_minor; + for (j = 0; j < IPMI_MAX_CHANNELS; j++) { + intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; + intf->channels[j].lun = 2; + } + if (slave_addr != 0) + intf->channels[0].address = slave_addr; + INIT_LIST_HEAD(&intf->users); + intf->handlers = handlers; + intf->send_info = send_info; + spin_lock_init(&intf->seq_lock); + for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { + intf->seq_table[j].inuse = 0; + intf->seq_table[j].seqid = 0; + } + intf->curr_seq = 0; +#ifdef CONFIG_PROC_FS + spin_lock_init(&intf->proc_entry_lock); +#endif + spin_lock_init(&intf->waiting_msgs_lock); + INIT_LIST_HEAD(&intf->waiting_msgs); + spin_lock_init(&intf->events_lock); + INIT_LIST_HEAD(&intf->waiting_events); + intf->waiting_events_count = 0; + spin_lock_init(&intf->cmd_rcvrs_lock); + INIT_LIST_HEAD(&intf->cmd_rcvrs); + init_waitqueue_head(&intf->waitq); + + spin_lock_init(&intf->counter_lock); + intf->proc_dir = NULL; rv = -ENOMEM; - - down_write(&interfaces_sem); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { if (ipmi_interfaces[i] == NULL) { - new_intf->intf_num = i; - new_intf->version_major = version_major; - new_intf->version_minor = version_minor; - for (j = 0; j < IPMI_MAX_CHANNELS; j++) { - new_intf->channels[j].address - = IPMI_BMC_SLAVE_ADDR; - new_intf->channels[j].lun = 2; - } - if (slave_addr != 0) - new_intf->channels[0].address = slave_addr; - rwlock_init(&(new_intf->users_lock)); - INIT_LIST_HEAD(&(new_intf->users)); - new_intf->handlers = handlers; - new_intf->send_info = send_info; - spin_lock_init(&(new_intf->seq_lock)); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { - new_intf->seq_table[j].inuse = 0; - new_intf->seq_table[j].seqid = 0; - } - new_intf->curr_seq = 0; -#ifdef CONFIG_PROC_FS - spin_lock_init(&(new_intf->proc_entry_lock)); -#endif - spin_lock_init(&(new_intf->waiting_msgs_lock)); - INIT_LIST_HEAD(&(new_intf->waiting_msgs)); - spin_lock_init(&(new_intf->events_lock)); - INIT_LIST_HEAD(&(new_intf->waiting_events)); - new_intf->waiting_events_count = 0; - rwlock_init(&(new_intf->cmd_rcvr_lock)); - init_waitqueue_head(&new_intf->waitq); - INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); - - spin_lock_init(&(new_intf->counter_lock)); - - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = new_intf; - spin_unlock_irqrestore(&interfaces_lock, flags); - + intf->intf_num = i; + /* Reserve the entry till we are done. */ + ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; rv = 0; - *intf = new_intf; break; } } + spin_unlock_irqrestore(&interfaces_lock, flags); + if (rv) + goto out; - downgrade_write(&interfaces_sem); - - if (rv == 0) - rv = add_proc_entries(*intf, i); - - if (rv == 0) { - if ((version_major > 1) - || ((version_major == 1) && (version_minor >= 5))) - { - /* Start scanning the channels to see what is - available. */ - (*intf)->null_user_handler = channel_handler; - (*intf)->curr_channel = 0; - rv = send_channel_info_cmd(*intf, 0); - if (rv) - goto out; + /* FIXME - this is an ugly kludge, this sets the intf for the + caller before sending any messages with it. */ + *new_intf = intf; - /* Wait for the channel info to be read. */ - up_read(&interfaces_sem); - wait_event((*intf)->waitq, - ((*intf)->curr_channel>=IPMI_MAX_CHANNELS)); - down_read(&interfaces_sem); + if ((version_major > 1) + || ((version_major == 1) && (version_minor >= 5))) + { + /* Start scanning the channels to see what is + available. */ + intf->null_user_handler = channel_handler; + intf->curr_channel = 0; + rv = send_channel_info_cmd(intf, 0); + if (rv) + goto out; - if (ipmi_interfaces[i] != new_intf) - /* Well, it went away. Just return. */ - goto out; - } else { - /* Assume a single IPMB channel at zero. */ - (*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; - (*intf)->channels[0].protocol - = IPMI_CHANNEL_PROTOCOL_IPMB; - } - - /* Call all the watcher interfaces to tell - them that a new interface is available. */ - call_smi_watchers(i); + /* Wait for the channel info to be read. */ + wait_event(intf->waitq, + intf->curr_channel >= IPMI_MAX_CHANNELS); + } else { + /* Assume a single IPMB channel at zero. */ + intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; + intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; } - out: - up_read(&interfaces_sem); + if (rv == 0) + rv = add_proc_entries(intf, i); + out: if (rv) { - if (new_intf->proc_dir) - remove_proc_entries(new_intf); - kfree(new_intf); + if (intf->proc_dir) + remove_proc_entries(intf); + kref_put(&intf->refcount, intf_free); + if (i < MAX_IPMI_INTERFACES) { + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = NULL; + spin_unlock_irqrestore(&interfaces_lock, flags); + } + } else { + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = intf; + spin_unlock_irqrestore(&interfaces_lock, flags); + call_smi_watchers(i); } return rv; } -static void free_recv_msg_list(struct list_head *q) -{ - struct ipmi_recv_msg *msg, *msg2; - - list_for_each_entry_safe(msg, msg2, q, link) { - list_del(&msg->link); - ipmi_free_recv_msg(msg); - } -} - -static void free_cmd_rcvr_list(struct list_head *q) -{ - struct cmd_rcvr *rcvr, *rcvr2; - - list_for_each_entry_safe(rcvr, rcvr2, q, link) { - list_del(&rcvr->link); - kfree(rcvr); - } -} - -static void clean_up_interface_data(ipmi_smi_t intf) -{ - int i; - - free_recv_msg_list(&(intf->waiting_msgs)); - free_recv_msg_list(&(intf->waiting_events)); - free_cmd_rcvr_list(&(intf->cmd_rcvrs)); - - for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { - if ((intf->seq_table[i].inuse) - && (intf->seq_table[i].recv_msg)) - { - ipmi_free_recv_msg(intf->seq_table[i].recv_msg); - } - } -} - int ipmi_unregister_smi(ipmi_smi_t intf) { - int rv = -ENODEV; int i; struct ipmi_smi_watcher *w; unsigned long flags; - down_write(&interfaces_sem); - if (list_empty(&(intf->users))) - { - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] == intf) { - remove_proc_entries(intf); - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = NULL; - clean_up_interface_data(intf); - spin_unlock_irqrestore(&interfaces_lock,flags); - kfree(intf); - rv = 0; - goto out_call_watcher; - } + spin_lock_irqsave(&interfaces_lock, flags); + for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + if (ipmi_interfaces[i] == intf) { + /* Set the interface number reserved until we + * are done. */ + ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; + intf->intf_num = -1; + break; } - } else { - rv = -EBUSY; } - up_write(&interfaces_sem); + spin_unlock_irqrestore(&interfaces_lock,flags); - return rv; + if (i == MAX_IPMI_INTERFACES) + return -ENODEV; - out_call_watcher: - downgrade_write(&interfaces_sem); + remove_proc_entries(intf); /* Call all the watcher interfaces to tell them that an interface is gone. */ down_read(&smi_watchers_sem); - list_for_each_entry(w, &smi_watchers, link) { + list_for_each_entry(w, &smi_watchers, link) w->smi_gone(i); - } up_read(&smi_watchers_sem); - up_read(&interfaces_sem); + + /* Allow the entry to be reused now. */ + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = NULL; + spin_unlock_irqrestore(&interfaces_lock,flags); + + kref_put(&intf->refcount, intf_free); return 0; } @@ -1998,14 +2033,14 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf, static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - ipmi_user_t user = NULL; - struct ipmi_ipmb_addr *ipmb_addr; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + ipmi_user_t user = NULL; + struct ipmi_ipmb_addr *ipmb_addr; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; if (msg->rsp_size < 10) { /* Message not big enough, just ignore it. */ @@ -2023,16 +2058,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[4] >> 2; cmd = msg->rsp[8]; - read_lock(&(intf->cmd_rcvr_lock)); - - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } - } - read_unlock(&(intf->cmd_rcvr_lock)); + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); if (user == NULL) { /* We didn't find a user, deliver an error response. */ @@ -2079,6 +2112,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, message, so requeue it for handling later. */ rv = 1; + kref_put(&user->refcount, free_user); } else { /* Extract the source address from the data. */ ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr; @@ -2179,14 +2213,14 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf, static int handle_lan_get_msg_cmd(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - ipmi_user_t user = NULL; - struct ipmi_lan_addr *lan_addr; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + ipmi_user_t user = NULL; + struct ipmi_lan_addr *lan_addr; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; if (msg->rsp_size < 12) { /* Message not big enough, just ignore it. */ @@ -2204,19 +2238,17 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[6] >> 2; cmd = msg->rsp[10]; - read_lock(&(intf->cmd_rcvr_lock)); - - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } - } - read_unlock(&(intf->cmd_rcvr_lock)); + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); if (user == NULL) { - /* We didn't find a user, deliver an error response. */ + /* We didn't find a user, just give up. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->unhandled_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); @@ -2235,6 +2267,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, message, so requeue it for handling later. */ rv = 1; + kref_put(&user->refcount, free_user); } else { /* Extract the source address from the data. */ lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr; @@ -2286,8 +2319,6 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, recv_msg->msg.data_len = msg->rsp_size - 3; } -/* This will be called with the intf->users_lock read-locked, so no need - to do that here. */ static int handle_read_event_rsp(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { @@ -2313,7 +2344,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, INIT_LIST_HEAD(&msgs); - spin_lock_irqsave(&(intf->events_lock), flags); + spin_lock_irqsave(&intf->events_lock, flags); spin_lock(&intf->counter_lock); intf->events++; @@ -2321,12 +2352,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, /* Allocate and fill in one message for every user that is getting events. */ - list_for_each_entry(user, &(intf->users), link) { + rcu_read_lock(); + list_for_each_entry_rcu(user, &intf->users, link) { if (! user->gets_events) continue; recv_msg = ipmi_alloc_recv_msg(); if (! recv_msg) { + rcu_read_unlock(); list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); @@ -2342,8 +2375,10 @@ static int handle_read_event_rsp(ipmi_smi_t intf, copy_event_into_recv_msg(recv_msg, msg); recv_msg->user = user; + kref_get(&user->refcount); list_add_tail(&(recv_msg->link), &msgs); } + rcu_read_unlock(); if (deliver_count) { /* Now deliver all the messages. */ @@ -2382,9 +2417,8 @@ static int handle_bmc_rsp(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { struct ipmi_recv_msg *recv_msg; - int found = 0; - struct ipmi_user *user; unsigned long flags; + struct ipmi_user *user; recv_msg = (struct ipmi_recv_msg *) msg->user_data; if (recv_msg == NULL) @@ -2396,16 +2430,9 @@ static int handle_bmc_rsp(ipmi_smi_t intf, return 0; } + user = recv_msg->user; /* Make sure the user still exists. */ - list_for_each_entry(user, &(intf->users), link) { - if (user == recv_msg->user) { - /* Found it, so we can deliver it */ - found = 1; - break; - } - } - - if ((! found) && recv_msg->user) { + if (user && !user->valid) { /* The user for the message went away, so give up. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->unhandled_local_responses++; @@ -2486,7 +2513,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, { /* It's a response to a response we sent. For this we deliver a send message response to the user. */ - struct ipmi_recv_msg *recv_msg = msg->user_data; + struct ipmi_recv_msg *recv_msg = msg->user_data; requeue = 0; if (msg->rsp_size < 2) @@ -2498,13 +2525,18 @@ static int handle_new_recv_msg(ipmi_smi_t intf, /* Invalid channel number */ goto out; - if (recv_msg) { - recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; - recv_msg->msg.data = recv_msg->msg_data; - recv_msg->msg.data_len = 1; - recv_msg->msg_data[0] = msg->rsp[2]; - deliver_response(recv_msg); - } + if (!recv_msg) + goto out; + + /* Make sure the user still exists. */ + if (!recv_msg->user || !recv_msg->user->valid) + goto out; + + recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; + recv_msg->msg.data = recv_msg->msg_data; + recv_msg->msg.data_len = 1; + recv_msg->msg_data[0] = msg->rsp[2]; + deliver_response(recv_msg); } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) && (msg->rsp[1] == IPMI_GET_MSG_CMD)) { @@ -2570,14 +2602,11 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, int rv; - /* Lock the user lock so the user can't go away while we are - working on it. */ - read_lock(&(intf->users_lock)); - if ((msg->data_size >= 2) && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) && (msg->data[1] == IPMI_SEND_MSG_CMD) - && (msg->user_data == NULL)) { + && (msg->user_data == NULL)) + { /* This is the local response to a command send, start the timer for these. The user_data will not be NULL if this is a response send, and we will let @@ -2612,46 +2641,46 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, } ipmi_free_smi_msg(msg); - goto out_unlock; + goto out; } /* To preserve message order, if the list is not empty, we tack this message onto the end of the list. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - if (!list_empty(&(intf->waiting_msgs))) { - list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); - goto out_unlock; + spin_lock_irqsave(&intf->waiting_msgs_lock, flags); + if (!list_empty(&intf->waiting_msgs)) { + list_add_tail(&msg->link, &intf->waiting_msgs); + spin_unlock(&intf->waiting_msgs_lock); + goto out; } - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); rv = handle_new_recv_msg(intf, msg); if (rv > 0) { /* Could not handle the message now, just add it to a list to handle later. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_lock(&intf->waiting_msgs_lock); + list_add_tail(&msg->link, &intf->waiting_msgs); + spin_unlock(&intf->waiting_msgs_lock); } else if (rv == 0) { ipmi_free_smi_msg(msg); } - out_unlock: - read_unlock(&(intf->users_lock)); + out: + return; } void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) { ipmi_user_t user; - read_lock(&(intf->users_lock)); - list_for_each_entry(user, &(intf->users), link) { + rcu_read_lock(); + list_for_each_entry_rcu(user, &intf->users, link) { if (! user->handler->ipmi_watchdog_pretimeout) continue; user->handler->ipmi_watchdog_pretimeout(user->handler_data); } - read_unlock(&(intf->users_lock)); + rcu_read_unlock(); } static void @@ -2691,8 +2720,65 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, return smi_msg; } -static void -ipmi_timeout_handler(long timeout_period) +static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, + struct list_head *timeouts, long timeout_period, + int slot, unsigned long *flags) +{ + struct ipmi_recv_msg *msg; + + if (!ent->inuse) + return; + + ent->timeout -= timeout_period; + if (ent->timeout > 0) + return; + + if (ent->retries_left == 0) { + /* The message has used all its retries. */ + ent->inuse = 0; + msg = ent->recv_msg; + list_add_tail(&msg->link, timeouts); + spin_lock(&intf->counter_lock); + if (ent->broadcast) + intf->timed_out_ipmb_broadcasts++; + else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + intf->timed_out_lan_commands++; + else + intf->timed_out_ipmb_commands++; + spin_unlock(&intf->counter_lock); + } else { + struct ipmi_smi_msg *smi_msg; + /* More retries, send again. */ + + /* Start with the max timer, set to normal + timer after the message is sent. */ + ent->timeout = MAX_MSG_TIMEOUT; + ent->retries_left--; + spin_lock(&intf->counter_lock); + if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + intf->retransmitted_lan_commands++; + else + intf->retransmitted_ipmb_commands++; + spin_unlock(&intf->counter_lock); + + smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, + ent->seqid); + if (! smi_msg) + return; + + spin_unlock_irqrestore(&intf->seq_lock, *flags); + /* Send the new message. We send with a zero + * priority. It timed out, I doubt time is + * that critical now, and high priority + * messages are really only for messages to the + * local MC, which don't get resent. */ + intf->handlers->sender(intf->send_info, + smi_msg, 0); + spin_lock_irqsave(&intf->seq_lock, *flags); + } +} + +static void ipmi_timeout_handler(long timeout_period) { ipmi_smi_t intf; struct list_head timeouts; @@ -2706,14 +2792,14 @@ ipmi_timeout_handler(long timeout_period) spin_lock(&interfaces_lock); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; - - read_lock(&(intf->users_lock)); + kref_get(&intf->refcount); + spin_unlock(&interfaces_lock); /* See if any waiting messages need to be processed. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - list_for_each_entry_safe(smi_msg, smi_msg2, &(intf->waiting_msgs), link) { + spin_lock_irqsave(&intf->waiting_msgs_lock, flags); + list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { if (! handle_new_recv_msg(intf, smi_msg)) { list_del(&smi_msg->link); ipmi_free_smi_msg(smi_msg); @@ -2723,73 +2809,23 @@ ipmi_timeout_handler(long timeout_period) break; } } - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); /* Go through the seq table and find any messages that have timed out, putting them in the timeouts list. */ - spin_lock_irqsave(&(intf->seq_lock), flags); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { - struct seq_table *ent = &(intf->seq_table[j]); - if (!ent->inuse) - continue; - - ent->timeout -= timeout_period; - if (ent->timeout > 0) - continue; - - if (ent->retries_left == 0) { - /* The message has used all its retries. */ - ent->inuse = 0; - msg = ent->recv_msg; - list_add_tail(&(msg->link), &timeouts); - spin_lock(&intf->counter_lock); - if (ent->broadcast) - intf->timed_out_ipmb_broadcasts++; - else if (ent->recv_msg->addr.addr_type - == IPMI_LAN_ADDR_TYPE) - intf->timed_out_lan_commands++; - else - intf->timed_out_ipmb_commands++; - spin_unlock(&intf->counter_lock); - } else { - struct ipmi_smi_msg *smi_msg; - /* More retries, send again. */ - - /* Start with the max timer, set to normal - timer after the message is sent. */ - ent->timeout = MAX_MSG_TIMEOUT; - ent->retries_left--; - spin_lock(&intf->counter_lock); - if (ent->recv_msg->addr.addr_type - == IPMI_LAN_ADDR_TYPE) - intf->retransmitted_lan_commands++; - else - intf->retransmitted_ipmb_commands++; - spin_unlock(&intf->counter_lock); - smi_msg = smi_from_recv_msg(intf, - ent->recv_msg, j, ent->seqid); - if (! smi_msg) - continue; - - spin_unlock_irqrestore(&(intf->seq_lock),flags); - /* Send the new message. We send with a zero - * priority. It timed out, I doubt time is - * that critical now, and high priority - * messages are really only for messages to the - * local MC, which don't get resent. */ - intf->handlers->sender(intf->send_info, - smi_msg, 0); - spin_lock_irqsave(&(intf->seq_lock), flags); - } - } - spin_unlock_irqrestore(&(intf->seq_lock), flags); - - list_for_each_entry_safe(msg, msg2, &timeouts, link) { + spin_lock_irqsave(&intf->seq_lock, flags); + for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) + check_msg_timeout(intf, &(intf->seq_table[j]), + &timeouts, timeout_period, j, + &flags); + spin_unlock_irqrestore(&intf->seq_lock, flags); + + list_for_each_entry_safe(msg, msg2, &timeouts, link) handle_msg_timeout(msg); - } - read_unlock(&(intf->users_lock)); + kref_put(&intf->refcount, intf_free); + spin_lock(&interfaces_lock); } spin_unlock(&interfaces_lock); } @@ -2802,7 +2838,7 @@ static void ipmi_request_event(void) spin_lock(&interfaces_lock); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; intf->handlers->request_events(intf->send_info); @@ -2884,6 +2920,13 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) return rv; } +void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) +{ + if (msg->user) + kref_put(&msg->user->refcount, free_user); + msg->done(msg); +} + #ifdef CONFIG_IPMI_PANIC_EVENT static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) @@ -2964,7 +3007,7 @@ static void send_panic_events(char *str) /* For every registered interface, send the event. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; /* Send the event announcing the panic. */ @@ -2995,7 +3038,7 @@ static void send_panic_events(char *str) int j; intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; /* First job here is to figure out where to send the @@ -3131,7 +3174,7 @@ static int panic_event(struct notifier_block *this, /* For every registered interface, set it to run to completion. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; intf->handlers->set_run_to_completion(intf->send_info, 1); @@ -3160,9 +3203,8 @@ static int ipmi_init_msghandler(void) printk(KERN_INFO "ipmi message handler version " IPMI_DRIVER_VERSION "\n"); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + for (i = 0; i < MAX_IPMI_INTERFACES; i++) ipmi_interfaces[i] = NULL; - } #ifdef CONFIG_PROC_FS proc_ipmi_root = proc_mkdir("ipmi", NULL); @@ -3258,3 +3300,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN); EXPORT_SYMBOL(ipmi_smi_add_proc_entry); EXPORT_SYMBOL(proc_ipmi_root); EXPORT_SYMBOL(ipmi_user_set_run_to_completion); +EXPORT_SYMBOL(ipmi_free_recv_msg); diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 938d55b813a5..d6276e60b3bf 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -256,10 +256,7 @@ struct ipmi_recv_msg }; /* Allocate and free the receive message. */ -static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) -{ - msg->done(msg); -} +void ipmi_free_recv_msg(struct ipmi_recv_msg *msg); struct ipmi_user_hndl { -- cgit v1.2.3 From e65845235c8120be63001fc1a4ac00c819194bbe Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:07 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - base changes Changes to the base kprobe infrastructure to track kprobe execution on a per-cpu basis. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kprobes.h | 31 ++++++++++++++++++++++--------- kernel/kprobes.c | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index e30afdca7917..6720305a31e8 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -106,6 +107,9 @@ struct jprobe { kprobe_opcode_t *entry; /* probe handling code to jump to */ }; +DECLARE_PER_CPU(struct kprobe *, current_kprobe); +DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + #ifdef ARCH_SUPPORTS_KRETPROBES extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); #else /* ARCH_SUPPORTS_KRETPROBES */ @@ -146,13 +150,6 @@ struct kretprobe_instance { void lock_kprobes(void); void unlock_kprobes(void); -/* kprobe running now on this CPU? */ -static inline int kprobe_running(void) -{ - extern unsigned int kprobe_cpu; - return kprobe_cpu == smp_processor_id(); -} - extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_copy_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); @@ -167,6 +164,22 @@ extern void free_insn_slot(kprobe_opcode_t *slot); struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); +/* kprobe_running() will just return the current_kprobe on this CPU */ +static inline struct kprobe *kprobe_running(void) +{ + return (__get_cpu_var(current_kprobe)); +} + +static inline void reset_current_kprobe(void) +{ + __get_cpu_var(current_kprobe) = NULL; +} + +static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) +{ + return (&__get_cpu_var(kprobe_ctlblk)); +} + int register_kprobe(struct kprobe *p); void unregister_kprobe(struct kprobe *p); int setjmp_pre_handler(struct kprobe *, struct pt_regs *); @@ -183,9 +196,9 @@ void add_rp_inst(struct kretprobe_instance *ri); void kprobe_flush_task(struct task_struct *tk); void recycle_rp_inst(struct kretprobe_instance *ri); #else /* CONFIG_KPROBES */ -static inline int kprobe_running(void) +static inline struct kprobe *kprobe_running(void) { - return 0; + return NULL; } static inline int register_kprobe(struct kprobe *p) { diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ce4915dd683a..6da8f9b33d1e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -51,7 +51,7 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; unsigned int kprobe_cpu = NR_CPUS; static DEFINE_SPINLOCK(kprobe_lock); -static struct kprobe *curr_kprobe; +static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; /* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -188,6 +188,17 @@ void __kprobes unlock_kprobes(void) local_irq_restore(flags); } +/* We have preemption disabled.. so it is safe to use __ versions */ +static inline void set_kprobe_instance(struct kprobe *kp) +{ + __get_cpu_var(kprobe_instance) = kp; +} + +static inline void reset_kprobe_instance(void) +{ + __get_cpu_var(kprobe_instance) = NULL; +} + /* You have to be holding the kprobe_lock */ struct kprobe __kprobes *get_kprobe(void *addr) { @@ -213,11 +224,11 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) list_for_each_entry(kp, &p->list, list) { if (kp->pre_handler) { - curr_kprobe = kp; + set_kprobe_instance(kp); if (kp->pre_handler(kp, regs)) return 1; } - curr_kprobe = NULL; + reset_kprobe_instance(); } return 0; } @@ -229,9 +240,9 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, list_for_each_entry(kp, &p->list, list) { if (kp->post_handler) { - curr_kprobe = kp; + set_kprobe_instance(kp); kp->post_handler(kp, regs, flags); - curr_kprobe = NULL; + reset_kprobe_instance(); } } return; @@ -240,12 +251,14 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr) { + struct kprobe *cur = __get_cpu_var(kprobe_instance); + /* * if we faulted "during" the execution of a user specified * probe handler, invoke just that probe's fault handler */ - if (curr_kprobe && curr_kprobe->fault_handler) { - if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr)) + if (cur && cur->fault_handler) { + if (cur->fault_handler(cur, regs, trapnr)) return 1; } return 0; @@ -253,15 +266,15 @@ static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) { - struct kprobe *kp = curr_kprobe; - if (curr_kprobe && kp->break_handler) { - if (kp->break_handler(kp, regs)) { - curr_kprobe = NULL; - return 1; - } + struct kprobe *cur = __get_cpu_var(kprobe_instance); + int ret = 0; + + if (cur && cur->break_handler) { + if (cur->break_handler(cur, regs)) + ret = 1; } - curr_kprobe = NULL; - return 0; + reset_kprobe_instance(); + return ret; } struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) -- cgit v1.2.3 From 9a0e3a86837ac7542e601c18346102c9d9e65fa5 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:08 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - i386 changes I386 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu, using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 126 +++++++++++++++++++++++++-------------------- include/asm-i386/kprobes.h | 17 ++++++ 2 files changed, 86 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index fd35039859e6..99565a66915d 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -37,16 +37,11 @@ #include #include -static struct kprobe *current_kprobe; -static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev; -static struct pt_regs jprobe_saved_regs; -static long *jprobe_saved_esp; -/* copy of the kernel stack at the probe fire time */ -static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; void jprobe_return_end(void); +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + /* * returns non-zero if opcode modifies the interrupt flag. */ @@ -91,29 +86,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) { } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; - kprobe_old_eflags_prev = kprobe_old_eflags; - kprobe_saved_eflags_prev = kprobe_saved_eflags; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.old_eflags = kcb->kprobe_old_eflags; + kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; - kprobe_old_eflags = kprobe_old_eflags_prev; - kprobe_saved_eflags = kprobe_saved_eflags_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_old_eflags = kcb->prev_kprobe.old_eflags; + kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags; } -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe = p; - kprobe_saved_eflags = kprobe_old_eflags + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags = (regs->eflags & (TF_MASK | IF_MASK)); if (is_IF_modifier(p->opcode)) - kprobe_saved_eflags &= ~IF_MASK; + kcb->kprobe_saved_eflags &= ~IF_MASK; } static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) @@ -157,6 +153,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) int ret = 0; kprobe_opcode_t *addr = NULL; unsigned long *lp; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Check if the application is using LDT entry for its code segment and * calculate the address by reading the base address from the LDT entry. @@ -175,10 +172,10 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { - if (kprobe_status == KPROBE_HIT_SS && + if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { regs->eflags &= ~TF_MASK; - regs->eflags |= kprobe_saved_eflags; + regs->eflags |= kcb->kprobe_saved_eflags; unlock_kprobes(); goto no_kprobe; } @@ -188,14 +185,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - set_current_kprobe(p, regs); + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); p->nmissed++; prepare_singlestep(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -235,8 +232,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * in post_kprobe_handler() */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p, regs); + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ @@ -244,7 +241,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) ss_probe: prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -312,6 +309,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->eip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -345,7 +343,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = (unsigned long *)®s->esp; unsigned long next_eip = 0; @@ -355,7 +354,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) switch (p->ainsn.insn[0]) { case 0x9c: /* pushfl */ *tos &= ~(TF_MASK | IF_MASK); - *tos |= kprobe_old_eflags; + *tos |= kcb->kprobe_old_eflags; break; case 0xc3: /* ret/lret */ case 0xcb: @@ -400,22 +399,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) */ static inline int post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_saved_eflags; + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_saved_eflags; /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } + reset_current_kprobe(); unlock_kprobes(); out: preempt_enable_no_resched(); @@ -434,14 +437,17 @@ out: /* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_old_eflags; + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_old_eflags; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -484,10 +490,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - jprobe_saved_regs = *regs; - jprobe_saved_esp = ®s->esp; - addr = (unsigned long)jprobe_saved_esp; + kcb->jprobe_saved_regs = *regs; + kcb->jprobe_saved_esp = ®s->esp; + addr = (unsigned long)(kcb->jprobe_saved_esp); /* * TBD: As Linus pointed out, gcc assumes that the callee @@ -496,7 +503,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) * we also save and restore enough stack bytes to cover * the argument area. */ - memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr)); + memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, + MIN_STACK_SIZE(addr)); regs->eflags &= ~IF_MASK; regs->eip = (unsigned long)(jp->entry); return 1; @@ -504,34 +512,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + asm volatile (" xchgl %%ebx,%%esp \n" " int3 \n" " .globl jprobe_return_end \n" " jprobe_return_end: \n" " nop \n"::"b" - (jprobe_saved_esp):"memory"); + (kcb->jprobe_saved_esp):"memory"); } int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); u8 *addr = (u8 *) (regs->eip - 1); - unsigned long stack_addr = (unsigned long)jprobe_saved_esp; + unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp); struct jprobe *jp = container_of(p, struct jprobe, kp); if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { - if (®s->esp != jprobe_saved_esp) { + if (®s->esp != kcb->jprobe_saved_esp) { struct pt_regs *saved_regs = - container_of(jprobe_saved_esp, struct pt_regs, esp); + container_of(kcb->jprobe_saved_esp, + struct pt_regs, esp); printk("current esp %p does not match saved esp %p\n", - ®s->esp, jprobe_saved_esp); + ®s->esp, kcb->jprobe_saved_esp); printk("Saved registers for jprobe %p\n", jp); show_registers(saved_regs); printk("Current registers\n"); show_registers(regs); BUG(); } - *regs = jprobe_saved_regs; - memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack, + *regs = kcb->jprobe_saved_regs; + memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); return 1; } diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h index 8b6d3a90cd78..ca916a892877 100644 --- a/include/asm-i386/kprobes.h +++ b/include/asm-i386/kprobes.h @@ -49,6 +49,23 @@ struct arch_specific_insn { kprobe_opcode_t insn[MAX_INSN_SIZE]; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long old_eflags; + unsigned long saved_eflags; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_old_eflags; + unsigned long kprobe_saved_eflags; + long *jprobe_saved_esp; + struct pt_regs jprobe_saved_regs; + kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; + struct prev_kprobe prev_kprobe; +}; /* trap3/1 are intr gates for kprobes. So, restore the status of IF, * if necessary, before executing the original int3/1 (trap) handler. -- cgit v1.2.3 From 8a5c4dc5e5d72b7802f5647082ccf3861a94f013 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:09 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - ia64 changes IA64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/kprobes.c | 83 +++++++++++++++++++++++++--------------------- include/asm-ia64/kprobes.h | 13 ++++++++ 2 files changed, 58 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 1e80ec80dd21..17e70b1b8d79 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -38,13 +38,8 @@ extern void jprobe_inst_return(void); -/* kprobe_status settings */ -#define KPROBE_HIT_ACTIVE 0x00000001 -#define KPROBE_HIT_SS 0x00000002 - -static struct kprobe *current_kprobe, *kprobe_prev; -static unsigned long kprobe_status, kprobe_status_prev; -static struct pt_regs jprobe_saved_regs; +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); enum instruction_type {A, I, M, F, B, L, X, u}; static enum instruction_type bundle_encoding[32][3] = { @@ -313,21 +308,22 @@ static int __kprobes valid_kprobe_addr(int template, int slot, return 0; } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; } -static inline void set_current_kprobe(struct kprobe *p) +static inline void set_current_kprobe(struct kprobe *p, + struct kprobe_ctlblk *kcb) { - current_kprobe = p; + __get_cpu_var(current_kprobe) = p; } static void kretprobe_trampoline(void) @@ -389,6 +385,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->cr_iip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -606,12 +603,13 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) int ret = 0; struct pt_regs *regs = args->regs; kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Handle recursion cases */ if (kprobe_running()) { p = get_kprobe(addr); if (p) { - if ( (kprobe_status == KPROBE_HIT_SS) && + if ((kcb->kprobe_status == KPROBE_HIT_SS) && (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { ia64_psr(regs)->ss = 0; unlock_kprobes(); @@ -623,17 +621,17 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - set_current_kprobe(p); + save_previous_kprobe(kcb); + set_current_kprobe(p, kcb); p->nmissed++; prepare_ss(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } else if (args->err == __IA64_BREAK_JPROBE) { /* * jprobe instrumented function just completed */ - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -668,8 +666,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) * in post_kprobes_handler() */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p); + set_current_kprobe(p, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) /* @@ -681,7 +679,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) ss_probe: prepare_ss(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -690,22 +688,25 @@ no_kprobe: static int __kprobes post_kprobes_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); + resume_execution(cur, regs); /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } - + reset_current_kprobe(); unlock_kprobes(); out: @@ -715,15 +716,18 @@ out: static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if (current_kprobe->fault_handler && - current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs); + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -761,9 +765,10 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr = ((struct fnptr *)(jp->entry))->ip; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* save architectural state */ - jprobe_saved_regs = *regs; + kcb->jprobe_saved_regs = *regs; /* after rfi, execute the jprobe instrumented function */ regs->cr_iip = addr & ~0xFULL; @@ -781,7 +786,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { - *regs = jprobe_saved_regs; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + *regs = kcb->jprobe_saved_regs; return 1; } diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index 573a3574a24f..592abb000e29 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h @@ -26,6 +26,7 @@ */ #include #include +#include #include #define MAX_INSN_SIZE 16 @@ -62,6 +63,18 @@ typedef struct _bundle { } quad1; } __attribute__((__aligned__(16))) bundle_t; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + struct pt_regs jprobe_saved_regs; + struct prev_kprobe prev_kprobe; +}; + #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES -- cgit v1.2.3 From 0dc036c91ac11b2b76bb91b59d8c7af919aa4a8d Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:10 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - ppc64 changes PPC64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/kprobes.c | 94 +++++++++++++++++++++++++------------------ include/asm-powerpc/kprobes.h | 15 +++++++ 2 files changed, 69 insertions(+), 40 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index 6071ee99f5cb..3f89f3e5584a 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -37,12 +37,8 @@ #include static DECLARE_MUTEX(kprobe_mutex); - -static struct kprobe *current_kprobe; -static unsigned long kprobe_status, kprobe_saved_msr; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; -static struct pt_regs jprobe_saved_regs; +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); int __kprobes arch_prepare_kprobe(struct kprobe *p) { @@ -108,18 +104,25 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) regs->nip = (unsigned long)p->ainsn.insn; } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) +{ + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr; +} + +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; - kprobe_saved_msr_prev = kprobe_saved_msr; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr; } -static inline void restore_previous_kprobe(void) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; - kprobe_saved_msr = kprobe_saved_msr_prev; + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_msr = regs->msr; } void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, @@ -145,6 +148,7 @@ static inline int kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; unsigned int *addr = (unsigned int *)regs->nip; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -153,10 +157,10 @@ static inline int kprobe_handler(struct pt_regs *regs) p = get_kprobe(addr); if (p) { kprobe_opcode_t insn = *p->ainsn.insn; - if (kprobe_status == KPROBE_HIT_SS && + if (kcb->kprobe_status == KPROBE_HIT_SS && is_trap(insn)) { regs->msr &= ~MSR_SE; - regs->msr |= kprobe_saved_msr; + regs->msr |= kcb->kprobe_saved_msr; unlock_kprobes(); goto no_kprobe; } @@ -166,15 +170,15 @@ static inline int kprobe_handler(struct pt_regs *regs) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - current_kprobe = p; - kprobe_saved_msr = regs->msr; + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); + kcb->kprobe_saved_msr = regs->msr; p->nmissed++; prepare_singlestep(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -214,16 +218,15 @@ static inline int kprobe_handler(struct pt_regs *regs) * in post_kprobe_handler(). */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - current_kprobe = p; - kprobe_saved_msr = regs->msr; + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + set_current_kprobe(p, regs, kcb); if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ return 1; ss_probe: prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -292,6 +295,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->nip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -324,22 +328,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) static inline int post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); - regs->msr |= kprobe_saved_msr; + resume_execution(cur, regs); + regs->msr |= kcb->kprobe_saved_msr; /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } + reset_current_kprobe(); unlock_kprobes(); out: preempt_enable_no_resched(); @@ -358,15 +366,18 @@ out: /* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs); regs->msr &= ~MSR_SE; - regs->msr |= kprobe_saved_msr; + regs->msr |= kcb->kprobe_saved_msr; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -411,8 +422,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs)); + memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); /* setup return addr to the jprobe handler routine */ regs->nip = (unsigned long)(((func_descr_t *)jp->entry)->entry); @@ -432,12 +444,14 @@ void __kprobes jprobe_return_end(void) int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + /* * FIXME - we should ideally be validating that we got here 'cos * of the "trap" in jprobe_return() above, before restoring the * saved regs... */ - memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs)); + memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); return 1; } diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h index b2f09f17fbe0..6cd0a3bfa280 100644 --- a/include/asm-powerpc/kprobes.h +++ b/include/asm-powerpc/kprobes.h @@ -27,6 +27,7 @@ */ #include #include +#include struct pt_regs; @@ -53,6 +54,20 @@ struct arch_specific_insn { kprobe_opcode_t *insn; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long saved_msr; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_saved_msr; + struct pt_regs jprobe_saved_regs; + struct prev_kprobe prev_kprobe; +}; + #ifdef CONFIG_KPROBES extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); -- cgit v1.2.3 From f215d985e936cf493959b365a10593b6d5f80447 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:11 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - sparc64 changes Sparc64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc64/kernel/kprobes.c | 131 +++++++++++++++++++++--------------------- include/asm-sparc64/kprobes.h | 20 +++++++ 2 files changed, 87 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 755a0d7d887f..b95984154dba 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -38,6 +38,9 @@ * - Mark that we are no longer actively in a kprobe. */ +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + int __kprobes arch_prepare_kprobe(struct kprobe *p) { return 0; @@ -66,46 +69,39 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) { } -static struct kprobe *current_kprobe; -static unsigned long current_kprobe_orig_tnpc; -static unsigned long current_kprobe_orig_tstate_pil; -static unsigned int kprobe_status; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_orig_tnpc_prev; -static unsigned long kprobe_orig_tstate_pil_prev; -static unsigned int kprobe_status_prev; - -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_status_prev = kprobe_status; - kprobe_orig_tnpc_prev = current_kprobe_orig_tnpc; - kprobe_orig_tstate_pil_prev = current_kprobe_orig_tstate_pil; - kprobe_prev = current_kprobe; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.orig_tnpc = kcb->kprobe_orig_tnpc; + kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_status = kprobe_status_prev; - current_kprobe_orig_tnpc = kprobe_orig_tnpc_prev; - current_kprobe_orig_tstate_pil = kprobe_orig_tstate_pil_prev; - current_kprobe = kprobe_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_orig_tnpc = kcb->prev_kprobe.orig_tnpc; + kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil; } -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe_orig_tnpc = regs->tnpc; - current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL); - current_kprobe = p; + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_orig_tnpc = regs->tnpc; + kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL); } -static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) +static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { regs->tstate |= TSTATE_PIL; /*single step inline, if it a breakpoint instruction*/ if (p->opcode == BREAKPOINT_INSTRUCTION) { regs->tpc = (unsigned long) p->addr; - regs->tnpc = current_kprobe_orig_tnpc; + regs->tnpc = kcb->kprobe_orig_tnpc; } else { regs->tpc = (unsigned long) &p->ainsn.insn[0]; regs->tnpc = (unsigned long) &p->ainsn.insn[1]; @@ -117,6 +113,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (kprobe_running()) { /* We *are* holding lock here, so this is safe. @@ -124,9 +121,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) */ p = get_kprobe(addr); if (p) { - if (kprobe_status == KPROBE_HIT_SS) { + if (kcb->kprobe_status == KPROBE_HIT_SS) { regs->tstate = ((regs->tstate & ~TSTATE_PIL) | - current_kprobe_orig_tstate_pil); + kcb->kprobe_orig_tstate_pil); unlock_kprobes(); goto no_kprobe; } @@ -136,14 +133,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - set_current_kprobe(p, regs); + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); p->nmissed++; - kprobe_status = KPROBE_REENTER; - prepare_singlestep(p, regs); + kcb->kprobe_status = KPROBE_REENTER; + prepare_singlestep(p, regs, kcb); return 1; } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } @@ -174,14 +171,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * in post_kprobes_handler() */ preempt_disable(); - set_current_kprobe(p, regs); - kprobe_status = KPROBE_HIT_ACTIVE; + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) return 1; ss_probe: - prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + prepare_singlestep(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -262,11 +259,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, * This function prepares to return from the post-single-step * breakpoint trap. */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, struct kprobe_ctlblk *kcb) { u32 insn = p->ainsn.insn[0]; - regs->tpc = current_kprobe_orig_tnpc; + regs->tpc = kcb->kprobe_orig_tnpc; regs->tnpc = relbranch_fixup(insn, (unsigned long) p->addr, (unsigned long) &p->ainsn.insn[0], @@ -274,26 +272,30 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) retpc_fixup(regs, insn, (unsigned long) p->addr); regs->tstate = ((regs->tstate & ~TSTATE_PIL) | - current_kprobe_orig_tstate_pil); + kcb->kprobe_orig_tstate_pil); } static inline int post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); + resume_execution(cur, regs, kcb); /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } + reset_current_kprobe(); unlock_kprobes(); out: preempt_enable_no_resched(); @@ -304,13 +306,16 @@ out: /* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -370,24 +375,21 @@ asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, } /* Jprobes support. */ -static struct pt_regs jprobe_saved_regs; -static struct pt_regs *jprobe_saved_regs_location; -static struct sparc_stackf jprobe_saved_stack; - int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - jprobe_saved_regs_location = regs; - memcpy(&jprobe_saved_regs, regs, sizeof(*regs)); + kcb->jprobe_saved_regs_location = regs; + memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs)); /* Save a whole stack frame, this gets arguments * pushed onto the stack after using up all the * arg registers. */ - memcpy(&jprobe_saved_stack, + memcpy(&(kcb->jprobe_saved_stack), (char *) (regs->u_regs[UREG_FP] + STACK_BIAS), - sizeof(jprobe_saved_stack)); + sizeof(kcb->jprobe_saved_stack)); regs->tpc = (unsigned long) jp->entry; regs->tnpc = ((unsigned long) jp->entry) + 0x4UL; @@ -411,14 +413,15 @@ extern void __show_regs(struct pt_regs * regs); int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u32 *addr = (u32 *) regs->tpc; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (addr == (u32 *) jprobe_return_trap_instruction) { - if (jprobe_saved_regs_location != regs) { + if (kcb->jprobe_saved_regs_location != regs) { printk("JPROBE: Current regs (%p) does not match " "saved regs (%p).\n", - regs, jprobe_saved_regs_location); + regs, kcb->jprobe_saved_regs_location); printk("JPROBE: Saved registers\n"); - __show_regs(jprobe_saved_regs_location); + __show_regs(kcb->jprobe_saved_regs_location); printk("JPROBE: Current registers\n"); __show_regs(regs); BUG(); @@ -427,11 +430,11 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * first so that UREG_FP is the original one for * the stack frame restore. */ - memcpy(regs, &jprobe_saved_regs, sizeof(*regs)); + memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs)); memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS), - &jprobe_saved_stack, - sizeof(jprobe_saved_stack)); + &(kcb->jprobe_saved_stack), + sizeof(kcb->jprobe_saved_stack)); return 1; } diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h index a8d326a598f0..7ba845320f5c 100644 --- a/include/asm-sparc64/kprobes.h +++ b/include/asm-sparc64/kprobes.h @@ -3,6 +3,7 @@ #include #include +#include typedef u32 kprobe_opcode_t; @@ -18,6 +19,25 @@ struct arch_specific_insn { kprobe_opcode_t insn[MAX_INSN_SIZE]; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned int status; + unsigned long orig_tnpc; + unsigned long orig_tstate_pil; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_orig_tnpc; + unsigned long kprobe_orig_tstate_pil; + long *jprobe_saved_esp; + struct pt_regs jprobe_saved_regs; + struct pt_regs *jprobe_saved_regs_location; + struct sparc_stackf jprobe_saved_stack; + struct prev_kprobe prev_kprobe; +}; + #ifdef CONFIG_KPROBES extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); -- cgit v1.2.3 From e7a510f92c1e482a7db05afd3cb84af1f4cfe0bc Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:12 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - x86_64 changes x86_64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using a arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/kprobes.c | 129 +++++++++++++++++++++++-------------------- include/asm-x86_64/kprobes.h | 19 +++++++ 2 files changed, 89 insertions(+), 59 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index ebfa2c9241ca..6cb40d133b7c 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -44,17 +44,10 @@ #include static DECLARE_MUTEX(kprobe_mutex); - -static struct kprobe *current_kprobe; -static unsigned long kprobe_status, kprobe_old_rflags, kprobe_saved_rflags; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev; -static struct pt_regs jprobe_saved_regs; -static long *jprobe_saved_rsp; void jprobe_return_end(void); -/* copy of the kernel stack at the probe fire time */ -static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); /* * returns non-zero if opcode modifies the interrupt flag. @@ -236,29 +229,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) up(&kprobe_mutex); } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; - kprobe_old_rflags_prev = kprobe_old_rflags; - kprobe_saved_rflags_prev = kprobe_saved_rflags; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.old_rflags = kcb->kprobe_old_rflags; + kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; - kprobe_old_rflags = kprobe_old_rflags_prev; - kprobe_saved_rflags = kprobe_saved_rflags_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_old_rflags = kcb->prev_kprobe.old_rflags; + kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags; } -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe = p; - kprobe_saved_rflags = kprobe_old_rflags + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags = (regs->eflags & (TF_MASK | IF_MASK)); if (is_IF_modifier(p->ainsn.insn)) - kprobe_saved_rflags &= ~IF_MASK; + kcb->kprobe_saved_rflags &= ~IF_MASK; } static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) @@ -301,6 +295,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -308,13 +303,13 @@ int __kprobes kprobe_handler(struct pt_regs *regs) Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { - if (kprobe_status == KPROBE_HIT_SS && + if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { regs->eflags &= ~TF_MASK; - regs->eflags |= kprobe_saved_rflags; + regs->eflags |= kcb->kprobe_saved_rflags; unlock_kprobes(); goto no_kprobe; - } else if (kprobe_status == KPROBE_HIT_SSDONE) { + } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) { /* TODO: Provide re-entrancy from * post_kprobes_handler() and avoid exception * stack corruption while single-stepping on @@ -322,6 +317,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) */ arch_disarm_kprobe(p); regs->rip = (unsigned long)p->addr; + reset_current_kprobe(); ret = 1; } else { /* We have reentered the kprobe_handler(), since @@ -331,15 +327,15 @@ int __kprobes kprobe_handler(struct pt_regs *regs) * of the new probe without calling any user * handlers. */ - save_previous_kprobe(); - set_current_kprobe(p, regs); + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); p->nmissed++; prepare_singlestep(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -374,8 +370,8 @@ int __kprobes kprobe_handler(struct pt_regs *regs) * in post_kprobe_handler() */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p, regs); + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ @@ -383,7 +379,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) ss_probe: prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -451,6 +447,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->rip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -484,7 +481,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = (unsigned long *)regs->rsp; unsigned long next_rip = 0; @@ -499,7 +497,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) switch (*insn) { case 0x9c: /* pushfl */ *tos &= ~(TF_MASK | IF_MASK); - *tos |= kprobe_old_rflags; + *tos |= kcb->kprobe_old_rflags; break; case 0xc3: /* ret/lret */ case 0xcb: @@ -544,24 +542,28 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) */ int __kprobes post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_saved_rflags; + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_saved_rflags; /* Restore the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } else { unlock_kprobes(); } + reset_current_kprobe(); out: preempt_enable_no_resched(); @@ -579,14 +581,17 @@ out: /* Interrupts disabled, kprobe_lock held. */ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_old_rflags; + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_old_rflags; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -629,10 +634,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - jprobe_saved_regs = *regs; - jprobe_saved_rsp = (long *) regs->rsp; - addr = (unsigned long)jprobe_saved_rsp; + kcb->jprobe_saved_regs = *regs; + kcb->jprobe_saved_rsp = (long *) regs->rsp; + addr = (unsigned long)(kcb->jprobe_saved_rsp); /* * As Linus pointed out, gcc assumes that the callee * owns the argument space and could overwrite it, e.g. @@ -640,7 +646,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) * we also save and restore enough stack bytes to cover * the argument area. */ - memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr)); + memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, + MIN_STACK_SIZE(addr)); regs->eflags &= ~IF_MASK; regs->rip = (unsigned long)(jp->entry); return 1; @@ -648,34 +655,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + asm volatile (" xchg %%rbx,%%rsp \n" " int3 \n" " .globl jprobe_return_end \n" " jprobe_return_end: \n" " nop \n"::"b" - (jprobe_saved_rsp):"memory"); + (kcb->jprobe_saved_rsp):"memory"); } int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); u8 *addr = (u8 *) (regs->rip - 1); - unsigned long stack_addr = (unsigned long)jprobe_saved_rsp; + unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp); struct jprobe *jp = container_of(p, struct jprobe, kp); if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { - if ((long *)regs->rsp != jprobe_saved_rsp) { + if ((long *)regs->rsp != kcb->jprobe_saved_rsp) { struct pt_regs *saved_regs = - container_of(jprobe_saved_rsp, struct pt_regs, rsp); + container_of(kcb->jprobe_saved_rsp, + struct pt_regs, rsp); printk("current rsp %p does not match saved rsp %p\n", - (long *)regs->rsp, jprobe_saved_rsp); + (long *)regs->rsp, kcb->jprobe_saved_rsp); printk("Saved registers for jprobe %p\n", jp); show_registers(saved_regs); printk("Current registers\n"); show_registers(regs); BUG(); } - *regs = jprobe_saved_regs; - memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack, + *regs = kcb->jprobe_saved_regs; + memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); return 1; } diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h index 6d6d883fdf6d..4dd7a7e148d4 100644 --- a/include/asm-x86_64/kprobes.h +++ b/include/asm-x86_64/kprobes.h @@ -25,6 +25,7 @@ */ #include #include +#include struct pt_regs; @@ -48,6 +49,24 @@ struct arch_specific_insn { kprobe_opcode_t *insn; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long old_rflags; + unsigned long saved_rflags; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_old_rflags; + unsigned long kprobe_saved_rflags; + long *jprobe_saved_rsp; + struct pt_regs jprobe_saved_regs; + kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; + struct prev_kprobe prev_kprobe; +}; + /* trap3/1 are intr gates for kprobes. So, restore the status of IF, * if necessary, before executing the original int3/1 (trap) handler. */ -- cgit v1.2.3 From 3516a46042508a495fac13c2e73530d936ebe015 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:13 -0800 Subject: [PATCH] Kprobes: Use RCU for (un)register synchronization - base changes Changes to the base kprobes infrastructure to use RCU for synchronization during kprobe registration and unregistration. These changes coupled with the arch kprobe changes (next in series): a. serialize registration and unregistration of kprobes. b. enable lockless execution of handlers. Handlers can now run in parallel. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kprobes.h | 9 ++--- kernel/kprobes.c | 103 ++++++++++++++++++++---------------------------- 2 files changed, 46 insertions(+), 66 deletions(-) (limited to 'include') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 6720305a31e8..cff281cf70cf 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include @@ -146,10 +148,7 @@ struct kretprobe_instance { }; #ifdef CONFIG_KPROBES -/* Locks kprobe: irq must be disabled */ -void lock_kprobes(void); -void unlock_kprobes(void); - +extern spinlock_t kretprobe_lock; extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_copy_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); @@ -160,7 +159,7 @@ extern void show_registers(struct pt_regs *regs); extern kprobe_opcode_t *get_insn_slot(void); extern void free_insn_slot(kprobe_opcode_t *slot); -/* Get the kprobe at this addr (if any). Must have called lock_kprobes */ +/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */ struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 6da8f9b33d1e..cfef426e4cdc 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -32,7 +32,6 @@ * added function-return probes. */ #include -#include #include #include #include @@ -49,8 +48,8 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; -unsigned int kprobe_cpu = NR_CPUS; -static DEFINE_SPINLOCK(kprobe_lock); +static DEFINE_SPINLOCK(kprobe_lock); /* Protects kprobe_table */ +DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; /* @@ -153,41 +152,6 @@ void __kprobes free_insn_slot(kprobe_opcode_t *slot) } } -/* Locks kprobe: irqs must be disabled */ -void __kprobes lock_kprobes(void) -{ - unsigned long flags = 0; - - /* Avoiding local interrupts to happen right after we take the kprobe_lock - * and before we get a chance to update kprobe_cpu, this to prevent - * deadlock when we have a kprobe on ISR routine and a kprobe on task - * routine - */ - local_irq_save(flags); - - spin_lock(&kprobe_lock); - kprobe_cpu = smp_processor_id(); - - local_irq_restore(flags); -} - -void __kprobes unlock_kprobes(void) -{ - unsigned long flags = 0; - - /* Avoiding local interrupts to happen right after we update - * kprobe_cpu and before we get a a chance to release kprobe_lock, - * this to prevent deadlock when we have a kprobe on ISR routine and - * a kprobe on task routine - */ - local_irq_save(flags); - - kprobe_cpu = NR_CPUS; - spin_unlock(&kprobe_lock); - - local_irq_restore(flags); -} - /* We have preemption disabled.. so it is safe to use __ versions */ static inline void set_kprobe_instance(struct kprobe *kp) { @@ -199,15 +163,20 @@ static inline void reset_kprobe_instance(void) __get_cpu_var(kprobe_instance) = NULL; } -/* You have to be holding the kprobe_lock */ +/* + * This routine is called either: + * - under the kprobe_lock spinlock - during kprobe_[un]register() + * OR + * - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c + */ struct kprobe __kprobes *get_kprobe(void *addr) { struct hlist_head *head; struct hlist_node *node; + struct kprobe *p; head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)]; - hlist_for_each(node, head) { - struct kprobe *p = hlist_entry(node, struct kprobe, hlist); + hlist_for_each_entry_rcu(p, node, head, hlist) { if (p->addr == addr) return p; } @@ -222,7 +191,7 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp; - list_for_each_entry(kp, &p->list, list) { + list_for_each_entry_rcu(kp, &p->list, list) { if (kp->pre_handler) { set_kprobe_instance(kp); if (kp->pre_handler(kp, regs)) @@ -238,7 +207,7 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, { struct kprobe *kp; - list_for_each_entry(kp, &p->list, list) { + list_for_each_entry_rcu(kp, &p->list, list) { if (kp->post_handler) { set_kprobe_instance(kp); kp->post_handler(kp, regs, flags); @@ -277,6 +246,7 @@ static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) return ret; } +/* Called with kretprobe_lock held */ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) { struct hlist_node *node; @@ -286,6 +256,7 @@ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) return NULL; } +/* Called with kretprobe_lock held */ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe *rp) { @@ -296,6 +267,7 @@ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe return NULL; } +/* Called with kretprobe_lock held */ void __kprobes add_rp_inst(struct kretprobe_instance *ri) { /* @@ -314,6 +286,7 @@ void __kprobes add_rp_inst(struct kretprobe_instance *ri) hlist_add_head(&ri->uflist, &ri->rp->used_instances); } +/* Called with kretprobe_lock held */ void __kprobes recycle_rp_inst(struct kretprobe_instance *ri) { /* remove rp inst off the rprobe_inst_table */ @@ -347,13 +320,13 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) struct hlist_node *node, *tmp; unsigned long flags = 0; - spin_lock_irqsave(&kprobe_lock, flags); + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { if (ri->task == tk) recycle_rp_inst(ri); } - spin_unlock_irqrestore(&kprobe_lock, flags); + spin_unlock_irqrestore(&kretprobe_lock, flags); } /* @@ -364,9 +337,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) { struct kretprobe *rp = container_of(p, struct kretprobe, kp); + unsigned long flags = 0; /*TODO: consider to only swap the RA after the last pre_handler fired */ + spin_lock_irqsave(&kretprobe_lock, flags); arch_prepare_kretprobe(rp, regs); + spin_unlock_irqrestore(&kretprobe_lock, flags); return 0; } @@ -397,13 +373,13 @@ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) struct kprobe *kp; if (p->break_handler) { - list_for_each_entry(kp, &old_p->list, list) { + list_for_each_entry_rcu(kp, &old_p->list, list) { if (kp->break_handler) return -EEXIST; } - list_add_tail(&p->list, &old_p->list); + list_add_tail_rcu(&p->list, &old_p->list); } else - list_add(&p->list, &old_p->list); + list_add_rcu(&p->list, &old_p->list); return 0; } @@ -421,18 +397,18 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) ap->break_handler = aggr_break_handler; INIT_LIST_HEAD(&ap->list); - list_add(&p->list, &ap->list); + list_add_rcu(&p->list, &ap->list); INIT_HLIST_NODE(&ap->hlist); - hlist_del(&p->hlist); - hlist_add_head(&ap->hlist, + hlist_del_rcu(&p->hlist); + hlist_add_head_rcu(&ap->hlist, &kprobe_table[hash_ptr(ap->addr, KPROBE_HASH_BITS)]); } /* * This is the second or subsequent kprobe at the address - handle * the intricacies - * TODO: Move kcalloc outside the spinlock + * TODO: Move kcalloc outside the spin_lock */ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) @@ -458,7 +434,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) { arch_disarm_kprobe(p); - hlist_del(&p->hlist); + hlist_del_rcu(&p->hlist); spin_unlock_irqrestore(&kprobe_lock, flags); arch_remove_kprobe(p); } @@ -466,11 +442,10 @@ static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) static inline void cleanup_aggr_kprobe(struct kprobe *old_p, struct kprobe *p, unsigned long flags) { - list_del(&p->list); - if (list_empty(&old_p->list)) { + list_del_rcu(&p->list); + if (list_empty(&old_p->list)) cleanup_kprobe(old_p, flags); - kfree(old_p); - } else + else spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -493,9 +468,9 @@ int __kprobes register_kprobe(struct kprobe *p) if ((ret = arch_prepare_kprobe(p)) != 0) goto rm_kprobe; + p->nmissed = 0; spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); - p->nmissed = 0; if (old_p) { ret = register_aggr_kprobe(old_p, p); goto out; @@ -503,7 +478,7 @@ int __kprobes register_kprobe(struct kprobe *p) arch_copy_kprobe(p); INIT_HLIST_NODE(&p->hlist); - hlist_add_head(&p->hlist, + hlist_add_head_rcu(&p->hlist, &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); arch_arm_kprobe(p); @@ -524,10 +499,16 @@ void __kprobes unregister_kprobe(struct kprobe *p) spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); if (old_p) { + /* cleanup_*_kprobe() does the spin_unlock_irqrestore */ if (old_p->pre_handler == aggr_pre_handler) cleanup_aggr_kprobe(old_p, p, flags); else cleanup_kprobe(p, flags); + + synchronize_sched(); + if (old_p->pre_handler == aggr_pre_handler && + list_empty(&old_p->list)) + kfree(old_p); } else spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -604,13 +585,13 @@ void __kprobes unregister_kretprobe(struct kretprobe *rp) unregister_kprobe(&rp->kp); /* No race here */ - spin_lock_irqsave(&kprobe_lock, flags); + spin_lock_irqsave(&kretprobe_lock, flags); free_rp_inst(rp); while ((ri = get_used_rp_inst(rp)) != NULL) { ri->rp = NULL; hlist_del(&ri->uflist); } - spin_unlock_irqrestore(&kprobe_lock, flags); + spin_unlock_irqrestore(&kretprobe_lock, flags); } static int __init init_kprobes(void) -- cgit v1.2.3 From d217d5450f11d8c907c0458d175b0dc999b4d06d Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:14 -0800 Subject: [PATCH] Kprobes: preempt_disable/enable() simplification Reorganize the preempt_disable/enable calls to eliminate the extra preempt depth. Changes based on Paul McKenney's review suggestions for the kprobes RCU changeset. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 25 +++++++++++++++---------- arch/ia64/kernel/kprobes.c | 37 ++++++++++++++++++++----------------- arch/ppc64/kernel/kprobes.c | 25 +++++++++++++++---------- arch/sparc64/kernel/kprobes.c | 21 +++++++++++++-------- arch/x86_64/kernel/kprobes.c | 29 +++++++++++++++-------------- include/linux/kprobes.h | 2 +- kernel/kprobes.c | 2 +- 7 files changed, 80 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index ad469299267a..32b0c24ab9a6 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -153,7 +153,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) int ret = 0; kprobe_opcode_t *addr = NULL; unsigned long *lp; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check if the application is using LDT entry for its code segment and * calculate the address by reading the base address from the LDT entry. @@ -221,11 +228,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -239,6 +241,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -310,8 +313,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -455,7 +458,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -467,14 +469,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -537,6 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) *regs = kcb->jprobe_saved_regs; memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index fddbac32d44a..96736a119c91 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -389,11 +389,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption - */ + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) + */ return 1; } @@ -604,7 +604,14 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) int ret = 0; struct pt_regs *regs = args->regs; kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Handle recursion cases */ if (kprobe_running()) { @@ -659,11 +666,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobes_handler() - */ - preempt_disable(); set_current_kprobe(p, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -681,6 +683,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -716,9 +719,6 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - if (!cur) - return 0; - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; @@ -737,7 +737,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch(val) { case DIE_BREAK: if (pre_kprobes_handler(args)) @@ -748,12 +747,15 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: - if (kprobes_fault_handler(args->regs, args->trapnr)) + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); + if (kprobe_running() && + kprobes_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); default: break; } - rcu_read_unlock(); return ret; } @@ -785,6 +787,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); *regs = kcb->jprobe_saved_regs; + preempt_enable_no_resched(); return 1; } diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index e0a25b35437f..511af54e6230 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -148,7 +148,14 @@ static inline int kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; unsigned int *addr = (unsigned int *)regs->nip; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -207,11 +214,6 @@ static inline int kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler(). - */ - preempt_disable(); kcb->kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p, regs, kcb); if (p->pre_handler && p->pre_handler(p, regs)) @@ -224,6 +226,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -296,8 +299,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption. + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -385,7 +388,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_BPT: if (kprobe_handler(args->regs)) @@ -396,14 +398,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -440,6 +444,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * saved regs... */ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); + preempt_enable_no_resched(); return 1; } diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 58a815e90373..96bd09b098f4 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -113,7 +113,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); if (kprobe_running()) { p = get_kprobe(addr); @@ -159,11 +166,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobes_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) @@ -175,6 +177,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -321,7 +324,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_DEBUG: if (kprobe_handler(args->regs)) @@ -333,14 +335,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -426,6 +430,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) &(kcb->jprobe_saved_stack), sizeof(kcb->jprobe_saved_stack)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 9bef2c8dc12c..dddeb678b440 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -286,16 +286,19 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, } } -/* - * Interrupts are disabled on entry as trap3 is an interrupt gate and they - * remain disabled thorough out this function. - */ int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -359,11 +362,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -377,6 +375,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -448,8 +447,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -594,7 +593,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -606,14 +604,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -675,6 +675,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) *regs = kcb->jprobe_saved_regs; memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index cff281cf70cf..e373c4a9de53 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -159,7 +159,7 @@ extern void show_registers(struct pt_regs *regs); extern kprobe_opcode_t *get_insn_slot(void); extern void free_insn_slot(kprobe_opcode_t *slot); -/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */ +/* Get the kprobe at this addr (if any) - called with preemption disabled */ struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index cfef426e4cdc..5beda378cc75 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -167,7 +167,7 @@ static inline void reset_kprobe_instance(void) * This routine is called either: * - under the kprobe_lock spinlock - during kprobe_[un]register() * OR - * - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c + * - with preemption disabled - from arch/xxx/kernel/kprobes.c */ struct kprobe __kprobes *get_kprobe(void *addr) { -- cgit v1.2.3 From 394b701ce4fbfde919a9bcbf84cb4820a7c6d47c Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:15 -0800 Subject: [PATCH] RapidIO support: core base Adds a RapidIO subsystem to the kernel. RIO is a switched fabric interconnect used in higher-end embedded applications. The curious can look at the specs over at http://www.rapidio.org The core code implements enumeration/discovery, management of devices/resources, and interfaces for RIO drivers. There's a lot more to do to take advantages of all the hardware features. However, this should provide a good base for folks with RIO hardware to start contributing. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/rapidio.tmpl | 160 ++++++++++++ MAINTAINERS | 6 + drivers/Makefile | 1 + drivers/rapidio/Kconfig | 18 ++ drivers/rapidio/Makefile | 6 + drivers/rapidio/rio-access.c | 175 +++++++++++++ drivers/rapidio/rio-driver.c | 229 +++++++++++++++++ drivers/rapidio/rio-sysfs.c | 230 +++++++++++++++++ drivers/rapidio/rio.c | 503 +++++++++++++++++++++++++++++++++++++ drivers/rapidio/rio.h | 57 +++++ include/asm-generic/vmlinux.lds.h | 7 + 12 files changed, 1393 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/rapidio.tmpl create mode 100644 drivers/rapidio/Kconfig create mode 100644 drivers/rapidio/Makefile create mode 100644 drivers/rapidio/rio-access.c create mode 100644 drivers/rapidio/rio-driver.c create mode 100644 drivers/rapidio/rio-sysfs.c create mode 100644 drivers/rapidio/rio.c create mode 100644 drivers/rapidio/rio.h (limited to 'include') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index fa3e29ad8a46..7018f5c6a447 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -10,7 +10,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \ - gadget.xml libata.xml mtdnand.xml librs.xml + gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/rapidio.tmpl b/Documentation/DocBook/rapidio.tmpl new file mode 100644 index 000000000000..1becf27ba27e --- /dev/null +++ b/Documentation/DocBook/rapidio.tmpl @@ -0,0 +1,160 @@ + + + ]> + + + + RapidIO Subsystem Guide + + + + Matt + Porter + +
+ mporter@kernel.crashing.org + mporter@mvista.com +
+
+
+
+ + + 2005 + MontaVista Software, Inc. + + + + + This documentation 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. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + RapidIO is a high speed switched fabric interconnect with + features aimed at the embedded market. RapidIO provides + support for memory-mapped I/O as well as message-based + transactions over the switched fabric network. RapidIO has + a standardized discovery mechanism not unlike the PCI bus + standard that allows simple detection of devices in a + network. + + + This documentation is provided for developers intending + to support RapidIO on new architectures, write new drivers, + or to understand the subsystem internals. + + + + + Known Bugs and Limitations + + + Bugs + None. ;) + + + Limitations + + + Access/management of RapidIO memory regions is not supported + Multiple host enumeration is not supported + + + + + + + RapidIO driver interface + + Drivers are provided a set of calls in order + to interface with the subsystem to gather info + on devices, request/map memory region resources, + and manage mailboxes/doorbells. + + + Functions +!Iinclude/linux/rio_drv.h +!Edrivers/rapidio/rio-driver.c +!Edrivers/rapidio/rio.c + + + + + Internals + + + This chapter contains the autogenerated documentation of the RapidIO + subsystem. + + + Structures +!Iinclude/linux/rio.h + + Enumeration and Discovery +!Idrivers/rapidio/rio-scan.c + + Driver functionality +!Idrivers/rapidio/rio.c +!Idrivers/rapidio/rio-access.c + + Device model support +!Idrivers/rapidio/rio-driver.c + + Sysfs support +!Idrivers/rapidio/rio-sysfs.c + + PPC32 support +!Iarch/ppc/kernel/rio.c +!Earch/ppc/syslib/ppc85xx_rio.c +!Iarch/ppc/syslib/ppc85xx_rio.c + + + + + Credits + + The following people have contributed to the RapidIO + subsystem directly or indirectly: + + Matt Portermporter@kernel.crashing.org + Randy Vinsonrvinson@mvista.com + Dan Malekdan@embeddedalley.com + + + + The following people have contributed to this document: + + Matt Portermporter@kernel.crashing.org + + + +
diff --git a/MAINTAINERS b/MAINTAINERS index 4cba302c2754..3ccbfa96eeec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2071,6 +2071,12 @@ P: Matt Mackall M: mpm@selenic.com S: Maintained +RAPIDIO SUBSYSTEM +P: Matt Porter +M: mporter@kernel.crashing.org +L: linux-kernel@vger.kernel.org +S: Maintained + REAL TIME CLOCK DRIVER P: Paul Gortmaker M: p_gortmaker@yahoo.com diff --git a/drivers/Makefile b/drivers/Makefile index 61c64f768366..fac1e1603097 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PCI) += pci/ usb/ obj-$(CONFIG_PARISC) += parisc/ +obj-$(CONFIG_RAPIDIO) += rapidio/ obj-y += video/ obj-$(CONFIG_ACPI) += acpi/ # PnP must come after ACPI since it will eventually need to check if acpi diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig new file mode 100644 index 000000000000..0b2d2c3579a7 --- /dev/null +++ b/drivers/rapidio/Kconfig @@ -0,0 +1,18 @@ +# +# RapidIO configuration +# +config RAPIDIO_8_BIT_TRANSPORT + bool "8-bit transport addressing" + depends on RAPIDIO + ---help--- + By default, the kernel assumes a 16-bit addressed RapidIO + network. By selecting this option, the kernel will support + an 8-bit addressed network. + +config RAPIDIO_DISC_TIMEOUT + int "Discovery timeout duration (seconds)" + depends on RAPIDIO + default "30" + ---help--- + Amount of time a discovery node waits for a host to complete + enumeration beforing giving up. diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile new file mode 100644 index 000000000000..7c0e1818de51 --- /dev/null +++ b/drivers/rapidio/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for RapidIO interconnect services +# +obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o + +obj-$(CONFIG_RAPIDIO) += switches/ diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c new file mode 100644 index 000000000000..b9fab2ae3a36 --- /dev/null +++ b/drivers/rapidio/rio-access.c @@ -0,0 +1,175 @@ +/* + * RapidIO configuration space access support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + +/* + * These interrupt-safe spinlocks protect all accesses to RIO + * configuration space and doorbell access. + */ +static spinlock_t rio_config_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t rio_doorbell_lock = SPIN_LOCK_UNLOCKED; + +/* + * Wrappers for all RIO configuration access functions. They just check + * alignment, do locking and call the low-level functions pointed to + * by rio_mport->ops. + */ + +#define RIO_8_BAD 0 +#define RIO_16_BAD (offset & 1) +#define RIO_32_BAD (offset & 3) + +/** + * RIO_LOP_READ - Generate rio_local_read_config_* functions + * @size: Size of configuration space read (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space read (1, 2, 4 bytes) + * + * Generates rio_local_read_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_LOP_READ(size,type,len) \ +int __rio_local_read_config_##size \ + (struct rio_mport *mport, u32 offset, type *value) \ +{ \ + int res; \ + unsigned long flags; \ + u32 data = 0; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->lcread(mport->id, offset, len, &data); \ + *value = (type)data; \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +/** + * RIO_LOP_WRITE - Generate rio_local_write_config_* functions + * @size: Size of configuration space write (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space write (1, 2, 4 bytes) + * + * Generates rio_local_write_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_LOP_WRITE(size,type,len) \ +int __rio_local_write_config_##size \ + (struct rio_mport *mport, u32 offset, type value) \ +{ \ + int res; \ + unsigned long flags; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->lcwrite(mport->id, offset, len, value); \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +RIO_LOP_READ(8, u8, 1) +RIO_LOP_READ(16, u16, 2) +RIO_LOP_READ(32, u32, 4) +RIO_LOP_WRITE(8, u8, 1) +RIO_LOP_WRITE(16, u16, 2) +RIO_LOP_WRITE(32, u32, 4) + +EXPORT_SYMBOL_GPL(__rio_local_read_config_8); +EXPORT_SYMBOL_GPL(__rio_local_read_config_16); +EXPORT_SYMBOL_GPL(__rio_local_read_config_32); +EXPORT_SYMBOL_GPL(__rio_local_write_config_8); +EXPORT_SYMBOL_GPL(__rio_local_write_config_16); +EXPORT_SYMBOL_GPL(__rio_local_write_config_32); + +/** + * RIO_OP_READ - Generate rio_mport_read_config_* functions + * @size: Size of configuration space read (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space read (1, 2, 4 bytes) + * + * Generates rio_mport_read_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_OP_READ(size,type,len) \ +int rio_mport_read_config_##size \ + (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \ +{ \ + int res; \ + unsigned long flags; \ + u32 data = 0; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->cread(mport->id, destid, hopcount, offset, len, &data); \ + *value = (type)data; \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +/** + * RIO_OP_WRITE - Generate rio_mport_write_config_* functions + * @size: Size of configuration space write (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space write (1, 2, 4 bytes) + * + * Generates rio_mport_write_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_OP_WRITE(size,type,len) \ +int rio_mport_write_config_##size \ + (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \ +{ \ + int res; \ + unsigned long flags; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->cwrite(mport->id, destid, hopcount, offset, len, value); \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +RIO_OP_READ(8, u8, 1) +RIO_OP_READ(16, u16, 2) +RIO_OP_READ(32, u32, 4) +RIO_OP_WRITE(8, u8, 1) +RIO_OP_WRITE(16, u16, 2) +RIO_OP_WRITE(32, u32, 4) + +EXPORT_SYMBOL_GPL(rio_mport_read_config_8); +EXPORT_SYMBOL_GPL(rio_mport_read_config_16); +EXPORT_SYMBOL_GPL(rio_mport_read_config_32); +EXPORT_SYMBOL_GPL(rio_mport_write_config_8); +EXPORT_SYMBOL_GPL(rio_mport_write_config_16); +EXPORT_SYMBOL_GPL(rio_mport_write_config_32); + +/** + * rio_mport_send_doorbell - Send a doorbell message + * + * @mport: RIO master port + * @destid: RIO device destination ID + * @data: Doorbell message data + * + * Send a doorbell message to a RIO device. The doorbell message + * has a 16-bit info field provided by the data argument. + */ +int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) +{ + int res; + unsigned long flags; + + spin_lock_irqsave(&rio_doorbell_lock, flags); + res = mport->ops->dsend(mport->id, destid, data); + spin_unlock_irqrestore(&rio_doorbell_lock, flags); + + return res; +} + +EXPORT_SYMBOL_GPL(rio_mport_send_doorbell); diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c new file mode 100644 index 000000000000..dc749609699a --- /dev/null +++ b/drivers/rapidio/rio-driver.c @@ -0,0 +1,229 @@ +/* + * RapidIO driver support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 "rio.h" + +/** + * rio_match_device - Tell if a RIO device has a matching RIO device id structure + * @id: the RIO device id structure to match against + * @rdev: the RIO device structure to match against + * + * Used from driver probe and bus matching to check whether a RIO device + * matches a device id structure provided by a RIO driver. Returns the + * matching &struct rio_device_id or %NULL if there is no match. + */ +static const struct rio_device_id *rio_match_device(const struct rio_device_id + *id, + const struct rio_dev *rdev) +{ + while (id->vid || id->asm_vid) { + if (((id->vid == RIO_ANY_ID) || (id->vid == rdev->vid)) && + ((id->did == RIO_ANY_ID) || (id->did == rdev->did)) && + ((id->asm_vid == RIO_ANY_ID) + || (id->asm_vid == rdev->asm_vid)) + && ((id->asm_did == RIO_ANY_ID) + || (id->asm_did == rdev->asm_did))) + return id; + id++; + } + return NULL; +} + +/** + * rio_dev_get - Increments the reference count of the RIO device structure + * + * @rdev: RIO device being referenced + * + * Each live reference to a device should be refcounted. + * + * Drivers for RIO devices should normally record such references in + * their probe() methods, when they bind to a device, and release + * them by calling rio_dev_put(), in their disconnect() methods. + */ +struct rio_dev *rio_dev_get(struct rio_dev *rdev) +{ + if (rdev) + get_device(&rdev->dev); + + return rdev; +} + +/** + * rio_dev_put - Release a use of the RIO device structure + * + * @rdev: RIO device being disconnected + * + * Must be called when a user of a device is finished with it. + * When the last user of the device calls this function, the + * memory of the device is freed. + */ +void rio_dev_put(struct rio_dev *rdev) +{ + if (rdev) + put_device(&rdev->dev); +} + +/** + * rio_device_probe - Tell if a RIO device structure has a matching RIO + * device id structure + * @id: the RIO device id structure to match against + * @dev: the RIO device structure to match against + * + * return 0 and set rio_dev->driver when drv claims rio_dev, else error + */ +static int rio_device_probe(struct device *dev) +{ + struct rio_driver *rdrv = to_rio_driver(dev->driver); + struct rio_dev *rdev = to_rio_dev(dev); + int error = -ENODEV; + const struct rio_device_id *id; + + if (!rdev->driver && rdrv->probe) { + if (!rdrv->id_table) + return error; + id = rio_match_device(rdrv->id_table, rdev); + rio_dev_get(rdev); + if (id) + error = rdrv->probe(rdev, id); + if (error >= 0) { + rdev->driver = rdrv; + error = 0; + rio_dev_put(rdev); + } + } + return error; +} + +/** + * rio_device_remove - Remove a RIO device from the system + * + * @dev: the RIO device structure to match against + * + * Remove a RIO device from the system. If it has an associated + * driver, then run the driver remove() method. Then update + * the reference count. + */ +static int rio_device_remove(struct device *dev) +{ + struct rio_dev *rdev = to_rio_dev(dev); + struct rio_driver *rdrv = rdev->driver; + + if (rdrv) { + if (rdrv->remove) + rdrv->remove(rdev); + rdev->driver = NULL; + } + + rio_dev_put(rdev); + + return 0; +} + +/** + * rio_register_driver - register a new RIO driver + * @rdrv: the RIO driver structure to register + * + * Adds a &struct rio_driver to the list of registered drivers + * Returns a negative value on error, otherwise 0. If no error + * occurred, the driver remains registered even if no device + * was claimed during registration. + */ +int rio_register_driver(struct rio_driver *rdrv) +{ + /* initialize common driver fields */ + rdrv->driver.name = rdrv->name; + rdrv->driver.bus = &rio_bus_type; + rdrv->driver.probe = rio_device_probe; + rdrv->driver.remove = rio_device_remove; + + /* register with core */ + return driver_register(&rdrv->driver); +} + +/** + * rio_unregister_driver - unregister a RIO driver + * @rdrv: the RIO driver structure to unregister + * + * Deletes the &struct rio_driver from the list of registered RIO + * drivers, gives it a chance to clean up by calling its remove() + * function for each device it was responsible for, and marks those + * devices as driverless. + */ +void rio_unregister_driver(struct rio_driver *rdrv) +{ + driver_unregister(&rdrv->driver); +} + +/** + * rio_match_bus - Tell if a RIO device structure has a matching RIO + * driver device id structure + * @dev: the standard device structure to match against + * @drv: the standard driver structure containing the ids to match against + * + * Used by a driver to check whether a RIO device present in the + * system is in its list of supported devices. Returns 1 if + * there is a matching &struct rio_device_id or 0 if there is + * no match. + */ +static int rio_match_bus(struct device *dev, struct device_driver *drv) +{ + struct rio_dev *rdev = to_rio_dev(dev); + struct rio_driver *rdrv = to_rio_driver(drv); + const struct rio_device_id *id = rdrv->id_table; + const struct rio_device_id *found_id; + + if (!id) + goto out; + + found_id = rio_match_device(id, rdev); + + if (found_id) + return 1; + + out:return 0; +} + +static struct device rio_bus = { + .bus_id = "rapidio", +}; + +struct bus_type rio_bus_type = { + .name = "rapidio", + .match = rio_match_bus, + .dev_attrs = rio_dev_attrs +}; + +/** + * rio_bus_init - Register the RapidIO bus with the device model + * + * Registers the RIO bus device and RIO bus type with the Linux + * device model. + */ +static int __init rio_bus_init(void) +{ + if (device_register(&rio_bus) < 0) + printk("RIO: failed to register RIO bus device\n"); + return bus_register(&rio_bus_type); +} + +postcore_initcall(rio_bus_init); + +EXPORT_SYMBOL_GPL(rio_register_driver); +EXPORT_SYMBOL_GPL(rio_unregister_driver); +EXPORT_SYMBOL_GPL(rio_bus_type); +EXPORT_SYMBOL_GPL(rio_dev_get); +EXPORT_SYMBOL_GPL(rio_dev_put); diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c new file mode 100644 index 000000000000..73218a37506d --- /dev/null +++ b/drivers/rapidio/rio-sysfs.c @@ -0,0 +1,230 @@ +/* + * RapidIO sysfs attributes and support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + +#include "rio.h" + +/* Sysfs support */ +#define rio_config_attr(field, format_string) \ +static ssize_t \ + field##_show(struct device *dev, char *buf) \ +{ \ + struct rio_dev *rdev = to_rio_dev(dev); \ + \ + return sprintf(buf, format_string, rdev->field); \ +} \ + +rio_config_attr(did, "0x%04x\n"); +rio_config_attr(vid, "0x%04x\n"); +rio_config_attr(device_rev, "0x%08x\n"); +rio_config_attr(asm_did, "0x%04x\n"); +rio_config_attr(asm_vid, "0x%04x\n"); +rio_config_attr(asm_rev, "0x%04x\n"); + +static ssize_t routes_show(struct device *dev, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + char *str = buf; + int i; + + if (!rdev->rswitch) + goto out; + + for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) { + if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE) + continue; + str += + sprintf(str, "%04x %02x\n", i, + rdev->rswitch->route_table[i]); + } + + out: + return (str - buf); +} + +struct device_attribute rio_dev_attrs[] = { + __ATTR_RO(did), + __ATTR_RO(vid), + __ATTR_RO(device_rev), + __ATTR_RO(asm_did), + __ATTR_RO(asm_vid), + __ATTR_RO(asm_rev), + __ATTR_RO(routes), + __ATTR_NULL, +}; + +static ssize_t +rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct rio_dev *dev = + to_rio_dev(container_of(kobj, struct device, kobj)); + unsigned int size = 0x100; + loff_t init_off = off; + u8 *data = (u8 *) buf; + + /* Several chips lock up trying to read undefined config space */ + if (capable(CAP_SYS_ADMIN)) + size = 0x200000; + + if (off > size) + return 0; + if (off + count > size) { + size -= off; + count = size; + } else { + size = count; + } + + if ((off & 1) && size) { + u8 val; + rio_read_config_8(dev, off, &val); + data[off - init_off] = val; + off++; + size--; + } + + if ((off & 3) && size > 2) { + u16 val; + rio_read_config_16(dev, off, &val); + data[off - init_off] = (val >> 8) & 0xff; + data[off - init_off + 1] = val & 0xff; + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val; + rio_read_config_32(dev, off, &val); + data[off - init_off] = (val >> 24) & 0xff; + data[off - init_off + 1] = (val >> 16) & 0xff; + data[off - init_off + 2] = (val >> 8) & 0xff; + data[off - init_off + 3] = val & 0xff; + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val; + rio_read_config_16(dev, off, &val); + data[off - init_off] = (val >> 8) & 0xff; + data[off - init_off + 1] = val & 0xff; + off += 2; + size -= 2; + } + + if (size > 0) { + u8 val; + rio_read_config_8(dev, off, &val); + data[off - init_off] = val; + off++; + --size; + } + + return count; +} + +static ssize_t +rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct rio_dev *dev = + to_rio_dev(container_of(kobj, struct device, kobj)); + unsigned int size = count; + loff_t init_off = off; + u8 *data = (u8 *) buf; + + if (off > 0x200000) + return 0; + if (off + count > 0x200000) { + size = 0x200000 - off; + count = size; + } + + if ((off & 1) && size) { + rio_write_config_8(dev, off, data[off - init_off]); + off++; + size--; + } + + if ((off & 3) && (size > 2)) { + u16 val = data[off - init_off + 1]; + val |= (u16) data[off - init_off] << 8; + rio_write_config_16(dev, off, val); + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val = data[off - init_off + 3]; + val |= (u32) data[off - init_off + 2] << 8; + val |= (u32) data[off - init_off + 1] << 16; + val |= (u32) data[off - init_off] << 24; + rio_write_config_32(dev, off, val); + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val = data[off - init_off + 1]; + val |= (u16) data[off - init_off] << 8; + rio_write_config_16(dev, off, val); + off += 2; + size -= 2; + } + + if (size) { + rio_write_config_8(dev, off, data[off - init_off]); + off++; + --size; + } + + return count; +} + +static struct bin_attribute rio_config_attr = { + .attr = { + .name = "config", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = 0x200000, + .read = rio_read_config, + .write = rio_write_config, +}; + +/** + * rio_create_sysfs_dev_files - create RIO specific sysfs files + * @rdev: device whose entries should be created + * + * Create files when @rdev is added to sysfs. + */ +int rio_create_sysfs_dev_files(struct rio_dev *rdev) +{ + sysfs_create_bin_file(&rdev->dev.kobj, &rio_config_attr); + + return 0; +} + +/** + * rio_remove_sysfs_dev_files - cleanup RIO specific sysfs files + * @rdev: device whose entries we should free + * + * Cleanup when @rdev is removed from sysfs. + */ +void rio_remove_sysfs_dev_files(struct rio_dev *rdev) +{ + sysfs_remove_bin_file(&rdev->dev.kobj, &rio_config_attr); +} diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c new file mode 100644 index 000000000000..adc299e2b07e --- /dev/null +++ b/drivers/rapidio/rio.c @@ -0,0 +1,503 @@ +/* + * RapidIO interconnect services + * (RapidIO Interconnect Specification, http://www.rapidio.org) + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "rio.h" + +static LIST_HEAD(rio_mports); + +/** + * rio_local_get_device_id - Get the base/extended device id for a port + * @port: RIO master port from which to get the deviceid + * + * Reads the base/extended device id from the local device + * implementing the master port. Returns the 8/16-bit device + * id. + */ +u16 rio_local_get_device_id(struct rio_mport *port) +{ + u32 result; + + rio_local_read_config_32(port, RIO_DID_CSR, &result); + + return (RIO_GET_DID(result)); +} + +/** + * rio_request_inb_mbox - request inbound mailbox service + * @mport: RIO master port from which to allocate the mailbox resource + * @mbox: Mailbox number to claim + * @entries: Number of entries in inbound mailbox queue + * @minb: Callback to execute when inbound message is received + * + * Requests ownership of an inbound mailbox resource and binds + * a callback function to the resource. Returns %0 on success. + */ +int rio_request_inb_mbox(struct rio_mport *mport, + int mbox, + int entries, + void (*minb) (struct rio_mport * mport, int mbox, + int slot)) +{ + int rc = 0; + + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_mbox_res(res, mbox, mbox); + + /* Make sure this mailbox isn't in use */ + if ((rc = + request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE], + res)) < 0) { + kfree(res); + goto out; + } + + mport->inb_msg[mbox].res = res; + + /* Hook the inbound message callback */ + mport->inb_msg[mbox].mcback = minb; + + rc = rio_open_inb_mbox(mport, mbox, entries); + } else + rc = -ENOMEM; + + out: + return rc; +} + +/** + * rio_release_inb_mbox - release inbound mailbox message service + * @mport: RIO master port from which to release the mailbox resource + * @mbox: Mailbox number to release + * + * Releases ownership of an inbound mailbox resource. Returns 0 + * if the request has been satisfied. + */ +int rio_release_inb_mbox(struct rio_mport *mport, int mbox) +{ + rio_close_inb_mbox(mport, mbox); + + /* Release the mailbox resource */ + return release_resource(mport->inb_msg[mbox].res); +} + +/** + * rio_request_outb_mbox - request outbound mailbox service + * @mport: RIO master port from which to allocate the mailbox resource + * @mbox: Mailbox number to claim + * @entries: Number of entries in outbound mailbox queue + * @moutb: Callback to execute when outbound message is sent + * + * Requests ownership of an outbound mailbox resource and binds + * a callback function to the resource. Returns 0 on success. + */ +int rio_request_outb_mbox(struct rio_mport *mport, + int mbox, + int entries, + void (*moutb) (struct rio_mport * mport, int mbox, + int slot)) +{ + int rc = 0; + + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_mbox_res(res, mbox, mbox); + + /* Make sure this outbound mailbox isn't in use */ + if ((rc = + request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE], + res)) < 0) { + kfree(res); + goto out; + } + + mport->outb_msg[mbox].res = res; + + /* Hook the inbound message callback */ + mport->outb_msg[mbox].mcback = moutb; + + rc = rio_open_outb_mbox(mport, mbox, entries); + } else + rc = -ENOMEM; + + out: + return rc; +} + +/** + * rio_release_outb_mbox - release outbound mailbox message service + * @mport: RIO master port from which to release the mailbox resource + * @mbox: Mailbox number to release + * + * Releases ownership of an inbound mailbox resource. Returns 0 + * if the request has been satisfied. + */ +int rio_release_outb_mbox(struct rio_mport *mport, int mbox) +{ + rio_close_outb_mbox(mport, mbox); + + /* Release the mailbox resource */ + return release_resource(mport->outb_msg[mbox].res); +} + +/** + * rio_setup_inb_dbell - bind inbound doorbell callback + * @mport: RIO master port to bind the doorbell callback + * @res: Doorbell message resource + * @dinb: Callback to execute when doorbell is received + * + * Adds a doorbell resource/callback pair into a port's + * doorbell event list. Returns 0 if the request has been + * satisfied. + */ +static int +rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, + void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, + u16 info)) +{ + int rc = 0; + struct rio_dbell *dbell; + + if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) { + rc = -ENOMEM; + goto out; + } + + dbell->res = res; + dbell->dinb = dinb; + + list_add_tail(&dbell->node, &mport->dbells); + + out: + return rc; +} + +/** + * rio_request_inb_dbell - request inbound doorbell message service + * @mport: RIO master port from which to allocate the doorbell resource + * @start: Doorbell info range start + * @end: Doorbell info range end + * @dinb: Callback to execute when doorbell is received + * + * Requests ownership of an inbound doorbell resource and binds + * a callback function to the resource. Returns 0 if the request + * has been satisfied. + */ +int rio_request_inb_dbell(struct rio_mport *mport, + u16 start, + u16 end, + void (*dinb) (struct rio_mport * mport, u16 src, + u16 dst, u16 info)) +{ + int rc = 0; + + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_dbell_res(res, start, end); + + /* Make sure these doorbells aren't in use */ + if ((rc = + request_resource(&mport->riores[RIO_DOORBELL_RESOURCE], + res)) < 0) { + kfree(res); + goto out; + } + + /* Hook the doorbell callback */ + rc = rio_setup_inb_dbell(mport, res, dinb); + } else + rc = -ENOMEM; + + out: + return rc; +} + +/** + * rio_release_inb_dbell - release inbound doorbell message service + * @mport: RIO master port from which to release the doorbell resource + * @start: Doorbell info range start + * @end: Doorbell info range end + * + * Releases ownership of an inbound doorbell resource and removes + * callback from the doorbell event list. Returns 0 if the request + * has been satisfied. + */ +int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) +{ + int rc = 0, found = 0; + struct rio_dbell *dbell; + + list_for_each_entry(dbell, &mport->dbells, node) { + if ((dbell->res->start == start) && (dbell->res->end == end)) { + found = 1; + break; + } + } + + /* If we can't find an exact match, fail */ + if (!found) { + rc = -EINVAL; + goto out; + } + + /* Delete from list */ + list_del(&dbell->node); + + /* Release the doorbell resource */ + rc = release_resource(dbell->res); + + /* Free the doorbell event */ + kfree(dbell); + + out: + return rc; +} + +/** + * rio_request_outb_dbell - request outbound doorbell message range + * @rdev: RIO device from which to allocate the doorbell resource + * @start: Doorbell message range start + * @end: Doorbell message range end + * + * Requests ownership of a doorbell message range. Returns a resource + * if the request has been satisfied or %NULL on failure. + */ +struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, + u16 end) +{ + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_dbell_res(res, start, end); + + /* Make sure these doorbells aren't in use */ + if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res) + < 0) { + kfree(res); + res = NULL; + } + } + + return res; +} + +/** + * rio_release_outb_dbell - release outbound doorbell message range + * @rdev: RIO device from which to release the doorbell resource + * @res: Doorbell resource to be freed + * + * Releases ownership of a doorbell message range. Returns 0 if the + * request has been satisfied. + */ +int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res) +{ + int rc = release_resource(res); + + kfree(res); + + return rc; +} + +/** + * rio_mport_get_feature - query for devices' extended features + * @port: Master port to issue transaction + * @local: Indicate a local master port or remote device access + * @destid: Destination ID of the device + * @hopcount: Number of switch hops to the device + * @ftr: Extended feature code + * + * Tell if a device supports a given RapidIO capability. + * Returns the offset of the requested extended feature + * block within the device's RIO configuration space or + * 0 in case the device does not support it. Possible + * values for @ftr: + * + * %RIO_EFB_PAR_EP_ID LP/LVDS EP Devices + * + * %RIO_EFB_PAR_EP_REC_ID LP/LVDS EP Recovery Devices + * + * %RIO_EFB_PAR_EP_FREE_ID LP/LVDS EP Free Devices + * + * %RIO_EFB_SER_EP_ID LP/Serial EP Devices + * + * %RIO_EFB_SER_EP_REC_ID LP/Serial EP Recovery Devices + * + * %RIO_EFB_SER_EP_FREE_ID LP/Serial EP Free Devices + */ +u32 +rio_mport_get_feature(struct rio_mport * port, int local, u16 destid, + u8 hopcount, int ftr) +{ + u32 asm_info, ext_ftr_ptr, ftr_header; + + if (local) + rio_local_read_config_32(port, RIO_ASM_INFO_CAR, &asm_info); + else + rio_mport_read_config_32(port, destid, hopcount, + RIO_ASM_INFO_CAR, &asm_info); + + ext_ftr_ptr = asm_info & RIO_EXT_FTR_PTR_MASK; + + while (ext_ftr_ptr) { + if (local) + rio_local_read_config_32(port, ext_ftr_ptr, + &ftr_header); + else + rio_mport_read_config_32(port, destid, hopcount, + ext_ftr_ptr, &ftr_header); + if (RIO_GET_BLOCK_ID(ftr_header) == ftr) + return ext_ftr_ptr; + if (!(ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header))) + break; + } + + return 0; +} + +/** + * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did + * @vid: RIO vid to match or %RIO_ANY_ID to match all vids + * @did: RIO did to match or %RIO_ANY_ID to match all dids + * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids + * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids + * @from: Previous RIO device found in search, or %NULL for new search + * + * Iterates through the list of known RIO devices. If a RIO device is + * found with a matching @vid, @did, @asm_vid, @asm_did, the reference + * count to the device is incrememted and a pointer to its device + * structure is returned. Otherwise, %NULL is returned. A new search + * is initiated by passing %NULL to the @from argument. Otherwise, if + * @from is not %NULL, searches continue from next device on the global + * list. The reference count for @from is always decremented if it is + * not %NULL. + */ +struct rio_dev *rio_get_asm(u16 vid, u16 did, + u16 asm_vid, u16 asm_did, struct rio_dev *from) +{ + struct list_head *n; + struct rio_dev *rdev; + + WARN_ON(in_interrupt()); + spin_lock(&rio_global_list_lock); + n = from ? from->global_list.next : rio_devices.next; + + while (n && (n != &rio_devices)) { + rdev = rio_dev_g(n); + if ((vid == RIO_ANY_ID || rdev->vid == vid) && + (did == RIO_ANY_ID || rdev->did == did) && + (asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) && + (asm_did == RIO_ANY_ID || rdev->asm_did == asm_did)) + goto exit; + n = n->next; + } + rdev = NULL; + exit: + rio_dev_put(from); + rdev = rio_dev_get(rdev); + spin_unlock(&rio_global_list_lock); + return rdev; +} + +/** + * rio_get_device - Begin or continue searching for a RIO device by vid/did + * @vid: RIO vid to match or %RIO_ANY_ID to match all vids + * @did: RIO did to match or %RIO_ANY_ID to match all dids + * @from: Previous RIO device found in search, or %NULL for new search + * + * Iterates through the list of known RIO devices. If a RIO device is + * found with a matching @vid and @did, the reference count to the + * device is incrememted and a pointer to its device structure is returned. + * Otherwise, %NULL is returned. A new search is initiated by passing %NULL + * to the @from argument. Otherwise, if @from is not %NULL, searches + * continue from next device on the global list. The reference count for + * @from is always decremented if it is not %NULL. + */ +struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from) +{ + return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); +} + +static void rio_fixup_device(struct rio_dev *dev) +{ +} + +static int __devinit rio_init(void) +{ + struct rio_dev *dev = NULL; + + while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) { + rio_fixup_device(dev); + } + return 0; +} + +device_initcall(rio_init); + +int rio_init_mports(void) +{ + int rc = 0; + struct rio_mport *port; + + list_for_each_entry(port, &rio_mports, node) { + if (!request_mem_region(port->iores.start, + port->iores.end - port->iores.start, + port->name)) { + printk(KERN_ERR + "RIO: Error requesting master port region %8.8lx-%8.8lx\n", + port->iores.start, port->iores.end - 1); + rc = -ENOMEM; + goto out; + } + + if (port->host_deviceid >= 0) + rio_enum_mport(port); + else + rio_disc_mport(port); + } + + out: + return rc; +} + +void rio_register_mport(struct rio_mport *port) +{ + list_add_tail(&port->node, &rio_mports); +} + +EXPORT_SYMBOL_GPL(rio_local_get_device_id); +EXPORT_SYMBOL_GPL(rio_get_device); +EXPORT_SYMBOL_GPL(rio_get_asm); +EXPORT_SYMBOL_GPL(rio_request_inb_dbell); +EXPORT_SYMBOL_GPL(rio_release_inb_dbell); +EXPORT_SYMBOL_GPL(rio_request_outb_dbell); +EXPORT_SYMBOL_GPL(rio_release_outb_dbell); +EXPORT_SYMBOL_GPL(rio_request_inb_mbox); +EXPORT_SYMBOL_GPL(rio_release_inb_mbox); +EXPORT_SYMBOL_GPL(rio_request_outb_mbox); +EXPORT_SYMBOL_GPL(rio_release_outb_mbox); diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h new file mode 100644 index 000000000000..f865a68cd3d5 --- /dev/null +++ b/drivers/rapidio/rio.h @@ -0,0 +1,57 @@ +/* + * RapidIO interconnect services + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + +/* Functions internal to the RIO core code */ + +extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, + u8 hopcount, int ftr); +extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); +extern int rio_enum_mport(struct rio_mport *mport); +extern int rio_disc_mport(struct rio_mport *mport); + +/* Structures internal to the RIO core code */ +extern struct device_attribute rio_dev_attrs[]; +extern spinlock_t rio_global_list_lock; + +/* Helpers internal to the RIO core code */ +#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ + static struct rio_route_ops __rio_route_ops __attribute_used__ \ + __attribute__((__section__(#section))) = { vid, did, add_hook, get_hook }; + +/** + * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations + * @vid: RIO vendor ID + * @did: RIO device ID + * @add_hook: Callback that adds a route entry + * @get_hook: Callback that gets a route entry + * + * Manipulating switch route tables in RIO is switch specific. This + * registers a switch by vendor and device ID with two callbacks for + * modifying and retrieving route entries in a switch. A &struct + * rio_route_ops is initialized with the ops and placed into a + * RIO-specific kernel section. + */ +#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \ + DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \ + vid, did, add_hook, get_hook) + +#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT +#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16) +#define RIO_SET_DID(x) ((x & 0x000000ff) << 16) +#else +#define RIO_GET_DID(x) (x & 0xffff) +#define RIO_SET_DID(x) (x & 0xffff) +#endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index a9c55490fb82..094d4917c1a9 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -35,6 +35,13 @@ VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \ } \ \ + /* RapidIO route ops */ \ + .rio_route : AT(ADDR(.rio_route) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_rio_route_ops) = .; \ + *(.rio_route_ops) \ + VMLINUX_SYMBOL(__end_rio_route_ops) = .; \ + } \ + \ /* Kernel symbol table: Normal symbols */ \ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start___ksymtab) = .; \ -- cgit v1.2.3 From 70a50ebd9a94533964c19f918dbbd66763e3f9e5 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:16 -0800 Subject: [PATCH] RapidIO support: core includes Add RapidIO core include files. The core code implements enumeration/discovery, management of devices/resources, and interfaces for RIO drivers. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rio.h | 321 ++++++++++++++++++++++++++++++++ include/linux/rio_drv.h | 469 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rio_ids.h | 24 +++ include/linux/rio_regs.h | 202 ++++++++++++++++++++ 4 files changed, 1016 insertions(+) create mode 100644 include/linux/rio.h create mode 100644 include/linux/rio_drv.h create mode 100644 include/linux/rio_ids.h create mode 100644 include/linux/rio_regs.h (limited to 'include') diff --git a/include/linux/rio.h b/include/linux/rio.h new file mode 100644 index 000000000000..930bbb7c3802 --- /dev/null +++ b/include/linux/rio.h @@ -0,0 +1,321 @@ +/* + * RapidIO interconnect services + * (RapidIO Interconnect Specification, http://www.rapidio.org) + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_H +#define LINUX_RIO_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#define RIO_ANY_DESTID 0xff +#define RIO_NO_HOPCOUNT -1 + +#define RIO_MAX_MPORT_RESOURCES 16 +#define RIO_MAX_DEV_RESOURCES 16 + +#define RIO_GLOBAL_TABLE 0xff /* Indicates access of a switch's + global routing table if it + has multiple (or per port) + tables */ + +#define RIO_INVALID_ROUTE 0xff /* Indicates that a route table + entry is invalid (no route + exists for the device ID) */ + +#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT +#define RIO_MAX_ROUTE_ENTRIES (1 << 8) +#else +#define RIO_MAX_ROUTE_ENTRIES (1 << 16) +#endif + +#define RIO_MAX_MBOX 4 +#define RIO_MAX_MSG_SIZE 0x1000 + +/* + * Error values that may be returned by RIO functions. + */ +#define RIO_SUCCESSFUL 0x00 +#define RIO_BAD_SIZE 0x81 + +/* + * For RIO devices, the region numbers are assigned this way: + * + * 0 RapidIO outbound doorbells + * 1-15 RapidIO memory regions + * + * For RIO master ports, the region number are assigned this way: + * + * 0 RapidIO inbound doorbells + * 1 RapidIO inbound mailboxes + * 1 RapidIO outbound mailboxes + */ +#define RIO_DOORBELL_RESOURCE 0 +#define RIO_INB_MBOX_RESOURCE 1 +#define RIO_OUTB_MBOX_RESOURCE 2 + +extern struct bus_type rio_bus_type; +extern struct list_head rio_devices; /* list of all devices */ + +struct rio_mport; + +/** + * struct rio_dev - RIO device info + * @global_list: Node in list of all RIO devices + * @net_list: Node in list of RIO devices in a network + * @net: Network this device is a part of + * @did: Device ID + * @vid: Vendor ID + * @device_rev: Device revision + * @asm_did: Assembly device ID + * @asm_vid: Assembly vendor ID + * @asm_rev: Assembly revision + * @efptr: Extended feature pointer + * @pef: Processing element features + * @swpinfo: Switch port info + * @src_ops: Source operation capabilities + * @dst_ops: Destination operation capabilities + * @rswitch: Pointer to &struct rio_switch if valid for this device + * @driver: Driver claiming this device + * @dev: Device model device + * @riores: RIO resources this device owns + * @destid: Network destination ID + */ +struct rio_dev { + struct list_head global_list; /* node in list of all RIO devices */ + struct list_head net_list; /* node in per net list */ + struct rio_net *net; /* RIO net this device resides in */ + u16 did; + u16 vid; + u32 device_rev; + u16 asm_did; + u16 asm_vid; + u16 asm_rev; + u16 efptr; + u32 pef; + u32 swpinfo; /* Only used for switches */ + u32 src_ops; + u32 dst_ops; + struct rio_switch *rswitch; /* RIO switch info */ + struct rio_driver *driver; /* RIO driver claiming this device */ + struct device dev; /* LDM device structure */ + struct resource riores[RIO_MAX_DEV_RESOURCES]; + u16 destid; +}; + +#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) +#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list) +#define to_rio_dev(n) container_of(n, struct rio_dev, dev) + +/** + * struct rio_msg - RIO message event + * @res: Mailbox resource + * @mcback: Message event callback + */ +struct rio_msg { + struct resource *res; + void (*mcback) (struct rio_mport * mport, int mbox, int slot); +}; + +/** + * struct rio_dbell - RIO doorbell event + * @node: Node in list of doorbell events + * @res: Doorbell resource + * @dinb: Doorbell event callback + */ +struct rio_dbell { + struct list_head node; + struct resource *res; + void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, u16 info); +}; + +/** + * struct rio_mport - RIO master port info + * @dbells: List of doorbell events + * @node: Node in global list of master ports + * @nnode: Node in network list of master ports + * @iores: I/O mem resource that this master port interface owns + * @riores: RIO resources that this master port interfaces owns + * @inb_msg: RIO inbound message event descriptors + * @outb_msg: RIO outbound message event descriptors + * @host_deviceid: Host device ID associated with this master port + * @ops: configuration space functions + * @id: Port ID, unique among all ports + * @index: Port index, unique among all port interfaces of the same type + * @name: Port name string + */ +struct rio_mport { + struct list_head dbells; /* list of doorbell events */ + struct list_head node; /* node in global list of ports */ + struct list_head nnode; /* node in net list of ports */ + struct resource iores; + struct resource riores[RIO_MAX_MPORT_RESOURCES]; + struct rio_msg inb_msg[RIO_MAX_MBOX]; + struct rio_msg outb_msg[RIO_MAX_MBOX]; + int host_deviceid; /* Host device ID */ + struct rio_ops *ops; /* maintenance transaction functions */ + unsigned char id; /* port ID, unique among all ports */ + unsigned char index; /* port index, unique among all port + interfaces of the same type */ + unsigned char name[40]; +}; + +/** + * struct rio_net - RIO network info + * @node: Node in global list of RIO networks + * @devices: List of devices in this network + * @mports: List of master ports accessing this network + * @hport: Default port for accessing this network + * @id: RIO network ID + */ +struct rio_net { + struct list_head node; /* node in list of networks */ + struct list_head devices; /* list of devices in this net */ + struct list_head mports; /* list of ports accessing net */ + struct rio_mport *hport; /* primary port for accessing net */ + unsigned char id; /* RIO network ID */ +}; + +/** + * struct rio_switch - RIO switch info + * @node: Node in global list of switches + * @switchid: Switch ID that is unique across a network + * @hopcount: Hopcount to this switch + * @destid: Associated destid in the path + * @route_table: Copy of switch routing table + * @add_entry: Callback for switch-specific route add function + * @get_entry: Callback for switch-specific route get function + */ +struct rio_switch { + struct list_head node; + u16 switchid; + u16 hopcount; + u16 destid; + u8 route_table[RIO_MAX_ROUTE_ENTRIES]; + int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port); + int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 * route_port); +}; + +/* Low-level architecture-dependent routines */ + +/** + * struct rio_ops - Low-level RIO configuration space operations + * @lcread: Callback to perform local (master port) read of config space. + * @lcwrite: Callback to perform local (master port) write of config space. + * @cread: Callback to perform network read of config space. + * @cwrite: Callback to perform network write of config space. + * @dsend: Callback to send a doorbell message. + */ +struct rio_ops { + int (*lcread) (int index, u32 offset, int len, u32 * data); + int (*lcwrite) (int index, u32 offset, int len, u32 data); + int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 * data); + int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 data); + int (*dsend) (int index, u16 destid, u16 data); +}; + +#define RIO_RESOURCE_MEM 0x00000100 +#define RIO_RESOURCE_DOORBELL 0x00000200 +#define RIO_RESOURCE_MAILBOX 0x00000400 + +#define RIO_RESOURCE_CACHEABLE 0x00010000 +#define RIO_RESOURCE_PCI 0x00020000 + +#define RIO_RESOURCE_BUSY 0x80000000 + +/** + * struct rio_driver - RIO driver info + * @node: Node in list of drivers + * @name: RIO driver name + * @id_table: RIO device ids to be associated with this driver + * @probe: RIO device inserted + * @remove: RIO device removed + * @suspend: RIO device suspended + * @resume: RIO device awakened + * @enable_wake: RIO device enable wake event + * @driver: LDM driver struct + * + * Provides info on a RIO device driver for insertion/removal and + * power management purposes. + */ +struct rio_driver { + struct list_head node; + char *name; + const struct rio_device_id *id_table; + int (*probe) (struct rio_dev * dev, const struct rio_device_id * id); + void (*remove) (struct rio_dev * dev); + int (*suspend) (struct rio_dev * dev, u32 state); + int (*resume) (struct rio_dev * dev); + int (*enable_wake) (struct rio_dev * dev, u32 state, int enable); + struct device_driver driver; +}; + +#define to_rio_driver(drv) container_of(drv,struct rio_driver, driver) + +/** + * struct rio_device_id - RIO device identifier + * @did: RIO device ID + * @vid: RIO vendor ID + * @asm_did: RIO assembly device ID + * @asm_vid: RIO assembly vendor ID + * + * Identifies a RIO device based on both the device/vendor IDs and + * the assembly device/vendor IDs. + */ +struct rio_device_id { + u16 did, vid; + u16 asm_did, asm_vid; +}; + +/** + * struct rio_route_ops - Per-switch route operations + * @vid: RIO vendor ID + * @did: RIO device ID + * @add_hook: Callback that adds a route entry + * @get_hook: Callback that gets a route entry + * + * Defines the operations that are necessary to manipulate the route + * tables for a particular RIO switch device. + */ +struct rio_route_ops { + u16 vid, did; + int (*add_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port); + int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 * route_port); +}; + +/* Architecture and hardware-specific functions */ +extern int rio_init_mports(void); +extern void rio_register_mport(struct rio_mport *); +extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int, + void *, size_t); +extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *); +extern void *rio_hw_get_inb_message(struct rio_mport *, int); +extern int rio_open_inb_mbox(struct rio_mport *, int, int); +extern void rio_close_inb_mbox(struct rio_mport *, int); +extern int rio_open_outb_mbox(struct rio_mport *, int, int); +extern void rio_close_outb_mbox(struct rio_mport *, int); + +#endif /* __KERNEL__ */ +#endif /* LINUX_RIO_H */ diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h new file mode 100644 index 000000000000..7483dfc0dfa3 --- /dev/null +++ b/include/linux/rio_drv.h @@ -0,0 +1,469 @@ +/* + * RapidIO driver services + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_DRV_H +#define LINUX_RIO_DRV_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +extern int __rio_local_read_config_32(struct rio_mport *port, u32 offset, + u32 * data); +extern int __rio_local_write_config_32(struct rio_mport *port, u32 offset, + u32 data); +extern int __rio_local_read_config_16(struct rio_mport *port, u32 offset, + u16 * data); +extern int __rio_local_write_config_16(struct rio_mport *port, u32 offset, + u16 data); +extern int __rio_local_read_config_8(struct rio_mport *port, u32 offset, + u8 * data); +extern int __rio_local_write_config_8(struct rio_mport *port, u32 offset, + u8 data); + +extern int rio_mport_read_config_32(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u32 * data); +extern int rio_mport_write_config_32(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u32 data); +extern int rio_mport_read_config_16(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u16 * data); +extern int rio_mport_write_config_16(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u16 data); +extern int rio_mport_read_config_8(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u8 * data); +extern int rio_mport_write_config_8(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u8 data); + +/** + * rio_local_read_config_32 - Read 32 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 32 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_32(struct rio_mport *port, u32 offset, + u32 * data) +{ + return __rio_local_read_config_32(port, offset, data); +} + +/** + * rio_local_write_config_32 - Write 32 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 32 bits of data to the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_write_config_32(struct rio_mport *port, u32 offset, + u32 data) +{ + return __rio_local_write_config_32(port, offset, data); +} + +/** + * rio_local_read_config_16 - Read 16 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 16 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_16(struct rio_mport *port, u32 offset, + u16 * data) +{ + return __rio_local_read_config_16(port, offset, data); +} + +/** + * rio_local_write_config_16 - Write 16 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 16 bits of data to the specified offset within the local + * device's configuration space. + */ + +static inline int rio_local_write_config_16(struct rio_mport *port, u32 offset, + u16 data) +{ + return __rio_local_write_config_16(port, offset, data); +} + +/** + * rio_local_read_config_8 - Read 8 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 8 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_8(struct rio_mport *port, u32 offset, + u8 * data) +{ + return __rio_local_read_config_8(port, offset, data); +} + +/** + * rio_local_write_config_8 - Write 8 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 8 bits of data to the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_write_config_8(struct rio_mport *port, u32 offset, + u8 data) +{ + return __rio_local_write_config_8(port, offset, data); +} + +/** + * rio_read_config_32 - Read 32 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 32 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset, + u32 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_32(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_32 - Write 32 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 32 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset, + u32 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_32(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_read_config_16 - Read 16 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 16 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset, + u16 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_16(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_16 - Write 16 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 16 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset, + u16 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_16(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_read_config_8 - Read 8 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 8 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_8(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_8 - Write 8 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 8 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_8(struct rio_dev *rdev, u32 offset, u8 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_8(rdev->net->hport, destid, hopcount, + offset, data); +}; + +extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, + u16 data); + +/** + * rio_send_doorbell - Send a doorbell message to a device + * @rdev: RIO device + * @data: Doorbell message data + * + * Send a doorbell message to a RIO device. The doorbell message + * has a 16-bit info field provided by the @data argument. + */ +static inline int rio_send_doorbell(struct rio_dev *rdev, u16 data) +{ + return rio_mport_send_doorbell(rdev->net->hport, rdev->destid, data); +}; + +/** + * rio_init_mbox_res - Initialize a RIO mailbox resource + * @res: resource struct + * @start: start of mailbox range + * @end: end of mailbox range + * + * This function is used to initialize the fields of a resource + * for use as a mailbox resource. It initializes a range of + * mailboxes using the start and end arguments. + */ +static inline void rio_init_mbox_res(struct resource *res, int start, int end) +{ + memset(res, 0, sizeof(struct resource)); + res->start = start; + res->end = end; + res->flags = RIO_RESOURCE_MAILBOX; +} + +/** + * rio_init_dbell_res - Initialize a RIO doorbell resource + * @res: resource struct + * @start: start of doorbell range + * @end: end of doorbell range + * + * This function is used to initialize the fields of a resource + * for use as a doorbell resource. It initializes a range of + * doorbell messages using the start and end arguments. + */ +static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) +{ + memset(res, 0, sizeof(struct resource)); + res->start = start; + res->end = end; + res->flags = RIO_RESOURCE_DOORBELL; +} + +/** + * RIO_DEVICE - macro used to describe a specific RIO device + * @vid: the 16 bit RIO vendor ID + * @did: the 16 bit RIO device ID + * + * This macro is used to create a struct rio_device_id that matches a + * specific device. The assembly vendor and assembly device fields + * will be set to %RIO_ANY_ID. + */ +#define RIO_DEVICE(dev,ven) \ + .did = (dev), .vid = (ven), \ + .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID + +/* Mailbox management */ +extern int rio_request_outb_mbox(struct rio_mport *, int, int, + void (*)(struct rio_mport *, int, int)); +extern int rio_release_outb_mbox(struct rio_mport *, int); + +/** + * rio_add_outb_message - Add RIO message to an outbound mailbox queue + * @mport: RIO master port containing the outbound queue + * @rdev: RIO device the message is be sent to + * @mbox: The outbound mailbox queue + * @buffer: Pointer to the message buffer + * @len: Length of the message buffer + * + * Adds a RIO message buffer to an outbound mailbox queue for + * transmission. Returns 0 on success. + */ +static inline int rio_add_outb_message(struct rio_mport *mport, + struct rio_dev *rdev, int mbox, + void *buffer, size_t len) +{ + return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len); +} + +extern int rio_request_inb_mbox(struct rio_mport *, int, int, + void (*)(struct rio_mport *, int, int)); +extern int rio_release_inb_mbox(struct rio_mport *, int); + +/** + * rio_add_inb_buffer - Add buffer to an inbound mailbox queue + * @mport: Master port containing the inbound mailbox + * @mbox: The inbound mailbox number + * @buffer: Pointer to the message buffer + * + * Adds a buffer to an inbound mailbox queue for reception. Returns + * 0 on success. + */ +static inline int rio_add_inb_buffer(struct rio_mport *mport, int mbox, + void *buffer) +{ + return rio_hw_add_inb_buffer(mport, mbox, buffer); +} + +/** + * rio_get_inb_message - Get A RIO message from an inbound mailbox queue + * @mport: Master port containing the inbound mailbox + * @mbox: The inbound mailbox number + * @buffer: Pointer to the message buffer + * + * Get a RIO message from an inbound mailbox queue. Returns 0 on success. + */ +static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) +{ + return rio_hw_get_inb_message(mport, mbox); +} + +/* Doorbell management */ +extern int rio_request_inb_dbell(struct rio_mport *, u16, u16, + void (*)(struct rio_mport *, u16, u16, u16)); +extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); +extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); +extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); + +/* Memory region management */ +int rio_claim_resource(struct rio_dev *, int); +int rio_request_regions(struct rio_dev *, char *); +void rio_release_regions(struct rio_dev *); +int rio_request_region(struct rio_dev *, int, char *); +void rio_release_region(struct rio_dev *, int); + +/* LDM support */ +int rio_register_driver(struct rio_driver *); +void rio_unregister_driver(struct rio_driver *); +struct rio_dev *rio_dev_get(struct rio_dev *); +void rio_dev_put(struct rio_dev *); + +/** + * rio_name - Get the unique RIO device identifier + * @rdev: RIO device + * + * Get the unique RIO device identifier. Returns the device + * identifier string. + */ +static inline char *rio_name(struct rio_dev *rdev) +{ + return rdev->dev.bus_id; +} + +/** + * rio_get_drvdata - Get RIO driver specific data + * @rdev: RIO device + * + * Get RIO driver specific data. Returns a pointer to the + * driver specific data. + */ +static inline void *rio_get_drvdata(struct rio_dev *rdev) +{ + return dev_get_drvdata(&rdev->dev); +} + +/** + * rio_set_drvdata - Set RIO driver specific data + * @rdev: RIO device + * @data: Pointer to driver specific data + * + * Set RIO driver specific data. device struct driver data pointer + * is set to the @data argument. + */ +static inline void rio_set_drvdata(struct rio_dev *rdev, void *data) +{ + dev_set_drvdata(&rdev->dev, data); +} + +/* Misc driver helpers */ +extern u16 rio_local_get_device_id(struct rio_mport *port); +extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from); +extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did, + struct rio_dev *from); + +#endif /* __KERNEL__ */ +#endif /* LINUX_RIO_DRV_H */ diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h new file mode 100644 index 000000000000..919d4e07d54e --- /dev/null +++ b/include/linux/rio_ids.h @@ -0,0 +1,24 @@ +/* + * RapidIO devices + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_IDS_H +#define LINUX_RIO_IDS_H + +#define RIO_ANY_ID 0xffff + +#define RIO_VID_FREESCALE 0x0002 +#define RIO_DID_MPC8560 0x0003 + +#define RIO_VID_TUNDRA 0x000d +#define RIO_DID_TSI500 0x0500 + +#endif /* LINUX_RIO_IDS_H */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h new file mode 100644 index 000000000000..f419be3be491 --- /dev/null +++ b/include/linux/rio_regs.h @@ -0,0 +1,202 @@ +/* + * RapidIO register definitions + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_REGS_H +#define LINUX_RIO_REGS_H + +/* + * In RapidIO, each device has a 2MB configuration space that is + * accessed via maintenance transactions. Portions of configuration + * space are standardized and/or reserved. + */ +#define RIO_DEV_ID_CAR 0x00 /* [I] Device Identity CAR */ +#define RIO_DEV_INFO_CAR 0x04 /* [I] Device Information CAR */ +#define RIO_ASM_ID_CAR 0x08 /* [I] Assembly Identity CAR */ +#define RIO_ASM_ID_MASK 0xffff0000 /* [I] Asm ID Mask */ +#define RIO_ASM_VEN_ID_MASK 0x0000ffff /* [I] Asm Vend Mask */ + +#define RIO_ASM_INFO_CAR 0x0c /* [I] Assembly Information CAR */ +#define RIO_ASM_REV_MASK 0xffff0000 /* [I] Asm Rev Mask */ +#define RIO_EXT_FTR_PTR_MASK 0x0000ffff /* [I] EF_PTR Mask */ + +#define RIO_PEF_CAR 0x10 /* [I] Processing Element Features CAR */ +#define RIO_PEF_BRIDGE 0x80000000 /* [I] Bridge */ +#define RIO_PEF_MEMORY 0x40000000 /* [I] MMIO */ +#define RIO_PEF_PROCESSOR 0x20000000 /* [I] Processor */ +#define RIO_PEF_SWITCH 0x10000000 /* [I] Switch */ +#define RIO_PEF_INB_MBOX 0x00f00000 /* [II] Mailboxes */ +#define RIO_PEF_INB_MBOX0 0x00800000 /* [II] Mailbox 0 */ +#define RIO_PEF_INB_MBOX1 0x00400000 /* [II] Mailbox 1 */ +#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */ +#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */ +#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */ +#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */ +#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */ +#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */ +#define RIO_PEF_ADDR_50 0x00000002 /* [I] 50 bits */ +#define RIO_PEF_ADDR_34 0x00000001 /* [I] 34 bits */ + +#define RIO_SWP_INFO_CAR 0x14 /* [I] Switch Port Information CAR */ +#define RIO_SWP_INFO_PORT_TOTAL_MASK 0x0000ff00 /* [I] Total number of ports */ +#define RIO_SWP_INFO_PORT_NUM_MASK 0x000000ff /* [I] Maintenance transaction port number */ +#define RIO_GET_TOTAL_PORTS(x) ((x & RIO_SWP_INFO_PORT_TOTAL_MASK) >> 8) + +#define RIO_SRC_OPS_CAR 0x18 /* [I] Source Operations CAR */ +#define RIO_SRC_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_SRC_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_SRC_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_SRC_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_SRC_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_SRC_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_SRC_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_SRC_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_SRC_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_SRC_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_SRC_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_SRC_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + +#define RIO_DST_OPS_CAR 0x1c /* Destination Operations CAR */ +#define RIO_DST_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_DST_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_DST_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_DST_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_DST_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_DST_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_DST_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_DST_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_DST_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_DST_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + + /* 0x20-0x3c *//* Reserved */ + +#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ +#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */ +#define RIO_MBOX0_FULL 0x40000000 /* [II] Mbox 0 full */ +#define RIO_MBOX0_EMPTY 0x20000000 /* [II] Mbox 0 empty */ +#define RIO_MBOX0_BUSY 0x10000000 /* [II] Mbox 0 busy */ +#define RIO_MBOX0_FAIL 0x08000000 /* [II] Mbox 0 fail */ +#define RIO_MBOX0_ERROR 0x04000000 /* [II] Mbox 0 error */ +#define RIO_MBOX1_AVAIL 0x00800000 /* [II] Mbox 1 avail */ +#define RIO_MBOX1_FULL 0x00200000 /* [II] Mbox 1 full */ +#define RIO_MBOX1_EMPTY 0x00200000 /* [II] Mbox 1 empty */ +#define RIO_MBOX1_BUSY 0x00100000 /* [II] Mbox 1 busy */ +#define RIO_MBOX1_FAIL 0x00080000 /* [II] Mbox 1 fail */ +#define RIO_MBOX1_ERROR 0x00040000 /* [II] Mbox 1 error */ +#define RIO_MBOX2_AVAIL 0x00008000 /* [II] Mbox 2 avail */ +#define RIO_MBOX2_FULL 0x00004000 /* [II] Mbox 2 full */ +#define RIO_MBOX2_EMPTY 0x00002000 /* [II] Mbox 2 empty */ +#define RIO_MBOX2_BUSY 0x00001000 /* [II] Mbox 2 busy */ +#define RIO_MBOX2_FAIL 0x00000800 /* [II] Mbox 2 fail */ +#define RIO_MBOX2_ERROR 0x00000400 /* [II] Mbox 2 error */ +#define RIO_MBOX3_AVAIL 0x00000080 /* [II] Mbox 3 avail */ +#define RIO_MBOX3_FULL 0x00000040 /* [II] Mbox 3 full */ +#define RIO_MBOX3_EMPTY 0x00000020 /* [II] Mbox 3 empty */ +#define RIO_MBOX3_BUSY 0x00000010 /* [II] Mbox 3 busy */ +#define RIO_MBOX3_FAIL 0x00000008 /* [II] Mbox 3 fail */ +#define RIO_MBOX3_ERROR 0x00000004 /* [II] Mbox 3 error */ + +#define RIO_WRITE_PORT_CSR 0x44 /* [I] Write Port CSR */ +#define RIO_DOORBELL_CSR 0x44 /* [II] Doorbell CSR */ +#define RIO_DOORBELL_AVAIL 0x80000000 /* [II] Doorbell avail */ +#define RIO_DOORBELL_FULL 0x40000000 /* [II] Doorbell full */ +#define RIO_DOORBELL_EMPTY 0x20000000 /* [II] Doorbell empty */ +#define RIO_DOORBELL_BUSY 0x10000000 /* [II] Doorbell busy */ +#define RIO_DOORBELL_FAILED 0x08000000 /* [II] Doorbell failed */ +#define RIO_DOORBELL_ERROR 0x04000000 /* [II] Doorbell error */ +#define RIO_WRITE_PORT_AVAILABLE 0x00000080 /* [I] Write Port Available */ +#define RIO_WRITE_PORT_FULL 0x00000040 /* [I] Write Port Full */ +#define RIO_WRITE_PORT_EMPTY 0x00000020 /* [I] Write Port Empty */ +#define RIO_WRITE_PORT_BUSY 0x00000010 /* [I] Write Port Busy */ +#define RIO_WRITE_PORT_FAILED 0x00000008 /* [I] Write Port Failed */ +#define RIO_WRITE_PORT_ERROR 0x00000004 /* [I] Write Port Error */ + + /* 0x48 *//* Reserved */ + +#define RIO_PELL_CTRL_CSR 0x4c /* [I] PE Logical Layer Control CSR */ +#define RIO_PELL_ADDR_66 0x00000004 /* [I] 66-bit addr */ +#define RIO_PELL_ADDR_50 0x00000002 /* [I] 50-bit addr */ +#define RIO_PELL_ADDR_34 0x00000001 /* [I] 34-bit addr */ + + /* 0x50-0x54 *//* Reserved */ + +#define RIO_LCSH_BA 0x58 /* [I] LCS High Base Address */ +#define RIO_LCSL_BA 0x5c /* [I] LCS Base Address */ + +#define RIO_DID_CSR 0x60 /* [III] Base Device ID CSR */ + + /* 0x64 *//* Reserved */ + +#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */ +#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */ + + /* 0x70-0xf8 *//* Reserved */ + /* 0x100-0xfff8 *//* [I] Extended Features Space */ + /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */ + +/* + * Extended Features Space is a configuration space area where + * functionality is mapped into extended feature blocks via a + * singly linked list of extended feature pointers (EFT_PTR). + * + * Each extended feature block can be identified/located in + * Extended Features Space by walking the extended feature + * list starting with the Extended Feature Pointer located + * in the Assembly Information CAR. + * + * Extended Feature Blocks (EFBs) are identified with an assigned + * EFB ID. Extended feature block offsets in the definitions are + * relative to the offset of the EFB within the Extended Features + * Space. + */ + +/* Helper macros to parse the Extended Feature Block header */ +#define RIO_EFB_PTR_MASK 0xffff0000 +#define RIO_EFB_ID_MASK 0x0000ffff +#define RIO_GET_BLOCK_PTR(x) ((x & RIO_EFB_PTR_MASK) >> 16) +#define RIO_GET_BLOCK_ID(x) (x & RIO_EFB_ID_MASK) + +/* Extended Feature Block IDs */ +#define RIO_EFB_PAR_EP_ID 0x0001 /* [IV] LP/LVDS EP Devices */ +#define RIO_EFB_PAR_EP_REC_ID 0x0002 /* [IV] LP/LVDS EP Recovery Devices */ +#define RIO_EFB_PAR_EP_FREE_ID 0x0003 /* [IV] LP/LVDS EP Free Devices */ +#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */ +#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */ +#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */ + +/* + * Physical 8/16 LP-LVDS + * ID=0x0001, Generic End Point Devices + * ID=0x0002, Generic End Point Devices, software assisted recovery option + * ID=0x0003, Generic End Point Free Devices + * + * Physical LP-Serial + * ID=0x0004, Generic End Point Devices + * ID=0x0005, Generic End Point Devices, software assisted recovery option + * ID=0x0006, Generic End Point Free Devices + */ +#define RIO_PORT_MNT_HEADER 0x0000 +#define RIO_PORT_REQ_CTL_CSR 0x0020 +#define RIO_PORT_RSP_CTL_CSR 0x0024 /* 0x0001/0x0002 */ +#define RIO_PORT_GEN_CTL_CSR 0x003c +#define RIO_PORT_GEN_HOST 0x80000000 +#define RIO_PORT_GEN_MASTER 0x40000000 +#define RIO_PORT_GEN_DISCOVERED 0x20000000 +#define RIO_PORT_N_MNT_REQ_CSR(x) (0x0040 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_MNT_RSP_CSR(x) (0x0044 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_ACK_STS_CSR(x) (0x0048 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_ERR_STS_CSR(x) (0x58 + x*0x20) +#define PORT_N_ERR_STS_PORT_OK 0x00000002 +#define RIO_PORT_N_CTL_CSR(x) (0x5c + x*0x20) + +#endif /* LINUX_RIO_REGS_H */ -- cgit v1.2.3 From fa78cc51794912b7e6ee98cd823fcc84cf79d04a Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:18 -0800 Subject: [PATCH] rapidio: core updates Addresses issues raised with the 2.6.12-rc6-mm1 RIO support. Fix dma_mask init, shrink some code, general cleanup. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/rio-scan.c | 35 ++++++++++------------------------- drivers/rapidio/rio.h | 3 +++ include/linux/rio.h | 2 ++ include/linux/rio_regs.h | 13 +++++++++++++ 4 files changed, 28 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 20e1d8f74597..4f7ed4bd3be9 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -33,7 +34,8 @@ static LIST_HEAD(rio_switches); static void rio_enum_timeout(unsigned long); -spinlock_t rio_global_list_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rio_global_list_lock); + static int next_destid = 0; static int next_switchid = 0; static int next_net = 0; @@ -55,9 +57,6 @@ static int rio_sport_phys_table[] = { -1, }; -extern struct rio_route_ops __start_rio_route_ops[]; -extern struct rio_route_ops __end_rio_route_ops[]; - /** * rio_get_device_id - Get the base/extended device id for a device * @port: RIO master port @@ -85,8 +84,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) * * Writes the base/extended device id from a device. */ -static void -rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) +static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) { rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR, RIO_SET_DID(did)); @@ -192,23 +190,9 @@ static int rio_enum_host(struct rio_mport *port) static int rio_device_has_destid(struct rio_mport *port, int src_ops, int dst_ops) { - if (((src_ops & RIO_SRC_OPS_READ) || - (src_ops & RIO_SRC_OPS_WRITE) || - (src_ops & RIO_SRC_OPS_ATOMIC_TST_SWP) || - (src_ops & RIO_SRC_OPS_ATOMIC_INC) || - (src_ops & RIO_SRC_OPS_ATOMIC_DEC) || - (src_ops & RIO_SRC_OPS_ATOMIC_SET) || - (src_ops & RIO_SRC_OPS_ATOMIC_CLR)) && - ((dst_ops & RIO_DST_OPS_READ) || - (dst_ops & RIO_DST_OPS_WRITE) || - (dst_ops & RIO_DST_OPS_ATOMIC_TST_SWP) || - (dst_ops & RIO_DST_OPS_ATOMIC_INC) || - (dst_ops & RIO_DST_OPS_ATOMIC_DEC) || - (dst_ops & RIO_DST_OPS_ATOMIC_SET) || - (dst_ops & RIO_DST_OPS_ATOMIC_CLR))) { - return 1; - } else - return 0; + u32 mask = RIO_OPS_READ | RIO_OPS_WRITE | RIO_OPS_ATOMIC_TST_SWP | RIO_OPS_ATOMIC_INC | RIO_OPS_ATOMIC_DEC | RIO_OPS_ATOMIC_SET | RIO_OPS_ATOMIC_CLR; + + return !!((src_ops | dst_ops) & mask); } /** @@ -383,8 +367,9 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rdev->dev.release = rio_release_dev; rio_dev_get(rdev); - rdev->dev.dma_mask = (u64 *) 0xffffffff; - rdev->dev.coherent_dma_mask = 0xffffffffULL; + rdev->dma_mask = DMA_32BIT_MASK; + rdev->dev.dma_mask = &rdev->dma_mask; + rdev->dev.coherent_dma_mask = DMA_32BIT_MASK; if ((rdev->pef & RIO_PEF_INB_DOORBELL) && (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index f865a68cd3d5..b242cee656e7 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h @@ -26,6 +26,9 @@ extern int rio_disc_mport(struct rio_mport *mport); extern struct device_attribute rio_dev_attrs[]; extern spinlock_t rio_global_list_lock; +extern struct rio_route_ops __start_rio_route_ops[]; +extern struct rio_route_ops __end_rio_route_ops[]; + /* Helpers internal to the RIO core code */ #define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ static struct rio_route_ops __rio_route_ops __attribute_used__ \ diff --git a/include/linux/rio.h b/include/linux/rio.h index 930bbb7c3802..5c29f2f477c2 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -91,6 +91,7 @@ struct rio_mport; * @swpinfo: Switch port info * @src_ops: Source operation capabilities * @dst_ops: Destination operation capabilities + * @dma_mask: Mask of bits of RIO address this device implements * @rswitch: Pointer to &struct rio_switch if valid for this device * @driver: Driver claiming this device * @dev: Device model device @@ -112,6 +113,7 @@ struct rio_dev { u32 swpinfo; /* Only used for switches */ u32 src_ops; u32 dst_ops; + u64 dma_mask; struct rio_switch *rswitch; /* RIO switch info */ struct rio_driver *driver; /* RIO driver claiming this device */ struct device dev; /* LDM device structure */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index f419be3be491..326540f9b54e 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -78,6 +78,19 @@ #define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ #define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ +#define RIO_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + /* 0x20-0x3c *//* Reserved */ #define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ -- cgit v1.2.3 From 2b0c28d7f8846f80a436093e906f5175d1fa8f55 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:19 -0800 Subject: [PATCH] RapidIO support: ppc32 Adds PPC32 RIO support. Init code for the MPC85xx RIO ports and glue for the STx GP3 board to use it. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/Kconfig | 8 + arch/ppc/configs/stx_gp3_defconfig | 86 ++- arch/ppc/kernel/Makefile | 1 + arch/ppc/kernel/rio.c | 52 ++ arch/ppc/platforms/85xx/mpc85xx_ads_common.c | 10 + arch/ppc/platforms/85xx/stx_gp3.c | 14 + arch/ppc/syslib/Makefile | 1 + arch/ppc/syslib/ppc85xx_rio.c | 932 +++++++++++++++++++++++++++ arch/ppc/syslib/ppc85xx_rio.h | 21 + include/asm-ppc/rio.h | 18 + 10 files changed, 1109 insertions(+), 34 deletions(-) create mode 100644 arch/ppc/kernel/rio.c create mode 100644 arch/ppc/syslib/ppc85xx_rio.c create mode 100644 arch/ppc/syslib/ppc85xx_rio.h create mode 100644 include/asm-ppc/rio.h (limited to 'include') diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index f8db33d55275..8fa51b0a32d2 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1257,6 +1257,14 @@ source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" +config RAPIDIO + bool "RapidIO support" if MPC8540 || MPC8560 + help + If you say Y here, the kernel will include drivers and + infrastructure code to support RapidIO interconnect devices. + +source "drivers/rapidio/Kconfig" + endmenu menu "Advanced setup" diff --git a/arch/ppc/configs/stx_gp3_defconfig b/arch/ppc/configs/stx_gp3_defconfig index 66dae8367659..3fedc43e44ad 100644 --- a/arch/ppc/configs/stx_gp3_defconfig +++ b/arch/ppc/configs/stx_gp3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-rc2 -# Wed Jan 26 14:32:58 2005 +# Linux kernel version: 2.6.12-rc4 +# Tue May 24 18:11:04 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y @@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # # Code maturity level options @@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup @@ -29,7 +31,6 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set @@ -37,6 +38,9 @@ CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -46,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -69,9 +74,11 @@ CONFIG_KMOD=y CONFIG_E500=y CONFIG_BOOKE=y CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set # CONFIG_SPE is not set CONFIG_MATH_EMULATION=y # CONFIG_CPU_FREQ is not set +# CONFIG_PM is not set CONFIG_85xx=y CONFIG_PPC_INDIRECT_PCI_BE=y @@ -96,6 +103,7 @@ CONFIG_HIGHMEM=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m # CONFIG_CMDLINE_BOOL is not set +CONFIG_ISA_DMA_API=y # # Bus options @@ -104,15 +112,15 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set +# CONFIG_PCI_DEBUG is not set # # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set - -# -# PC-card bridges -# +CONFIG_RAPIDIO=y +CONFIG_RAPIDIO_8_BIT_TRANSPORT=y +CONFIG_RAPIDIO_DISC_TIMEOUT=30 # # Advanced setup @@ -152,7 +160,7 @@ CONFIG_PARPORT=m CONFIG_PARPORT_PC=m # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_OTHER is not set +# CONFIG_PARPORT_GSC is not set # CONFIG_PARPORT_1284 is not set # @@ -264,7 +272,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set @@ -274,7 +281,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=m @@ -283,6 +289,7 @@ CONFIG_SCSI_QLA2XXX=m # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set @@ -322,7 +329,6 @@ CONFIG_NET=y # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -431,7 +437,7 @@ CONFIG_IP_NF_NAT_FTP=m # # Network testing # -# CONFIG_NET_PKTGEN is not set +CONFIG_NET_PKTGEN=y # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set @@ -499,6 +505,7 @@ CONFIG_GFAR_NAPI=y # Wan interfaces # # CONFIG_WAN is not set +CONFIG_RIONET=y # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set @@ -535,20 +542,6 @@ CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=m # CONFIG_INPUT_EVBUG is not set -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PARKBD is not set -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set - # # Input Device Drivers # @@ -566,6 +559,19 @@ CONFIG_MOUSE_PS2=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y + # # Character devices # @@ -590,6 +596,7 @@ CONFIG_SERIAL_CPM_SCC2=y # CONFIG_SERIAL_CPM_SCC4 is not set # CONFIG_SERIAL_CPM_SMC1 is not set # CONFIG_SERIAL_CPM_SMC2 is not set +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -625,6 +632,11 @@ CONFIG_DRM=m # CONFIG_DRM_SIS is not set # CONFIG_RAW_DRIVER is not set +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + # # I2C support # @@ -648,12 +660,12 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_SCx200_ACB is not set @@ -677,7 +689,9 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set @@ -688,9 +702,11 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set @@ -700,10 +716,12 @@ CONFIG_I2C_ALGOBIT=m # # Other I2C Chip support # +# CONFIG_SENSORS_DS1337 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -732,7 +750,6 @@ CONFIG_I2C_ALGOBIT=m # Graphics support # # CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -752,13 +769,9 @@ CONFIG_SOUND=m # # USB support # -# CONFIG_USB is not set CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information -# +# CONFIG_USB is not set # # USB Gadget Support @@ -789,6 +802,10 @@ CONFIG_JBD_DEBUG=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set + +# +# XFS support +# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -859,7 +876,6 @@ CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -942,8 +958,10 @@ CONFIG_ZLIB_INFLATE=m # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=y # CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index c610ca933a25..76a55a438f23 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_RAPIDIO) += rio.o obj-$(CONFIG_KGDB) += ppc-stub.o obj-$(CONFIG_SMP) += smp.o smp-tbsync.o obj-$(CONFIG_TAU) += temp.o diff --git a/arch/ppc/kernel/rio.c b/arch/ppc/kernel/rio.c new file mode 100644 index 000000000000..29487fedfc76 --- /dev/null +++ b/arch/ppc/kernel/rio.c @@ -0,0 +1,52 @@ +/* + * RapidIO PPC32 support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + +/** + * platform_rio_init - Do platform specific RIO init + * + * Any platform specific initialization of RapdIO + * hardware is done here as well as registration + * of any active master ports in the system. + */ +void __attribute__ ((weak)) + platform_rio_init(void) +{ + printk(KERN_WARNING "RIO: No platform_rio_init() present\n"); +} + +/** + * ppc_rio_init - Do PPC32 RIO init + * + * Calls platform-specific RIO init code and then calls + * rio_init_mports() to initialize any master ports that + * have been registered with the RIO subsystem. + */ +static int __init ppc_rio_init(void) +{ + printk(KERN_INFO "RIO: RapidIO init\n"); + + /* Platform specific initialization */ + platform_rio_init(); + + /* Enumerate all registered ports */ + rio_init_mports(); + + return 0; +} + +subsys_initcall(ppc_rio_init); diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index bd3ac0136756..16ad092d8a06 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c @@ -45,6 +45,8 @@ #include +#include + #include #ifndef CONFIG_PCI @@ -189,3 +191,11 @@ mpc85xx_exclude_device(u_char bus, u_char devfn) } #endif /* CONFIG_PCI */ + +#ifdef CONFIG_RAPIDIO +void platform_rio_init(void) +{ + /* 512MB RIO LAW at 0xc0000000 */ + mpc85xx_rio_setup(0xc0000000, 0x20000000); +} +#endif /* CONFIG_RAPIDIO */ diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 1e1b85f8193a..15ce9d070634 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ #include #include +#include unsigned char __res[sizeof(bd_t)]; @@ -273,6 +275,18 @@ int mpc85xx_exclude_device(u_char bus, u_char devfn) } #endif /* CONFIG_PCI */ +#ifdef CONFIG_RAPIDIO +void +platform_rio_init(void) +{ + /* + * The STx firmware configures the RapidIO Local Access Window + * at 0xc0000000 with a size of 512MB. + */ + mpc85xx_rio_setup(0xc0000000, 0x20000000); +} +#endif /* CONFIG_RAPIDIO */ + void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index dcd168f9a7aa..5bd33baac243 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o ifeq ($(CONFIG_40x),y) obj-$(CONFIG_PCI) += pci_auto.o ppc405_pci.o +obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o endif endif obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c new file mode 100644 index 000000000000..9d09c2715e0a --- /dev/null +++ b/arch/ppc/syslib/ppc85xx_rio.c @@ -0,0 +1,932 @@ +/* + * MPC85xx RapidIO support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 +#include +#include +#include + +#include + +#define RIO_REGS_BASE (CCSRBAR + 0xc0000) +#define RIO_ATMU_REGS_OFFSET 0x10c00 +#define RIO_MSG_REGS_OFFSET 0x11000 +#define RIO_MAINT_WIN_SIZE 0x400000 +#define RIO_DBELL_WIN_SIZE 0x1000 + +#define RIO_MSG_OMR_MUI 0x00000002 +#define RIO_MSG_OSR_TE 0x00000080 +#define RIO_MSG_OSR_QOI 0x00000020 +#define RIO_MSG_OSR_QFI 0x00000010 +#define RIO_MSG_OSR_MUB 0x00000004 +#define RIO_MSG_OSR_EOMI 0x00000002 +#define RIO_MSG_OSR_QEI 0x00000001 + +#define RIO_MSG_IMR_MI 0x00000002 +#define RIO_MSG_ISR_TE 0x00000080 +#define RIO_MSG_ISR_QFI 0x00000010 +#define RIO_MSG_ISR_DIQI 0x00000001 + +#define RIO_MSG_DESC_SIZE 32 +#define RIO_MSG_BUFFER_SIZE 4096 +#define RIO_MIN_TX_RING_SIZE 2 +#define RIO_MAX_TX_RING_SIZE 2048 +#define RIO_MIN_RX_RING_SIZE 2 +#define RIO_MAX_RX_RING_SIZE 2048 + +#define DOORBELL_DMR_DI 0x00000002 +#define DOORBELL_DSR_TE 0x00000080 +#define DOORBELL_DSR_QFI 0x00000010 +#define DOORBELL_DSR_DIQI 0x00000001 +#define DOORBELL_TID_OFFSET 0x03 +#define DOORBELL_SID_OFFSET 0x05 +#define DOORBELL_INFO_OFFSET 0x06 + +#define DOORBELL_MESSAGE_SIZE 0x08 +#define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET)) +#define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET)) +#define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET)) + +#define is_power_of_2(x) (((x) & ((x) - 1)) == 0) + +struct rio_atmu_regs { + u32 rowtar; + u32 pad1; + u32 rowbar; + u32 pad2; + u32 rowar; + u32 pad3[3]; +}; + +struct rio_msg_regs { + u32 omr; + u32 osr; + u32 pad1; + u32 odqdpar; + u32 pad2; + u32 osar; + u32 odpr; + u32 odatr; + u32 odcr; + u32 pad3; + u32 odqepar; + u32 pad4[13]; + u32 imr; + u32 isr; + u32 pad5; + u32 ifqdpar; + u32 pad6; + u32 ifqepar; + u32 pad7[250]; + u32 dmr; + u32 dsr; + u32 pad8; + u32 dqdpar; + u32 pad9; + u32 dqepar; + u32 pad10[26]; + u32 pwmr; + u32 pwsr; + u32 pad11; + u32 pwqbar; +}; + +struct rio_tx_desc { + u32 res1; + u32 saddr; + u32 dport; + u32 dattr; + u32 res2; + u32 res3; + u32 dwcnt; + u32 res4; +}; + +static u32 regs_win; +static struct rio_atmu_regs *atmu_regs; +static struct rio_atmu_regs *maint_atmu_regs; +static struct rio_atmu_regs *dbell_atmu_regs; +static u32 dbell_win; +static u32 maint_win; +static struct rio_msg_regs *msg_regs; + +static struct rio_dbell_ring { + void *virt; + dma_addr_t phys; +} dbell_ring; + +static struct rio_msg_tx_ring { + void *virt; + dma_addr_t phys; + void *virt_buffer[RIO_MAX_TX_RING_SIZE]; + dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE]; + int tx_slot; + int size; +} msg_tx_ring; + +static struct rio_msg_rx_ring { + void *virt; + dma_addr_t phys; + void *virt_buffer[RIO_MAX_RX_RING_SIZE]; + int rx_slot; + int size; +} msg_rx_ring; + +/** + * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message + * @index: ID of RapidIO interface + * @destid: Destination ID of target device + * @data: 16-bit info field of RapidIO doorbell message + * + * Sends a MPC85xx doorbell message. Returns %0 on success or + * %-EINVAL on failure. + */ +static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data) +{ + pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n", + index, destid, data); + out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22); + out_be16((void *)(dbell_win), data); + + return 0; +} + +/** + * mpc85xx_local_config_read - Generate a MPC85xx local config space read + * @index: ID of RapdiIO interface + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @data: Value to be read into + * + * Generates a MPC85xx local configuration space read. Returns %0 on + * success or %-EINVAL on failure. + */ +static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data) +{ + pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index, + offset); + *data = in_be32((void *)(regs_win + offset)); + + return 0; +} + +/** + * mpc85xx_local_config_write - Generate a MPC85xx local config space write + * @index: ID of RapdiIO interface + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @data: Value to be written + * + * Generates a MPC85xx local configuration space write. Returns %0 on + * success or %-EINVAL on failure. + */ +static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data) +{ + pr_debug + ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n", + index, offset, data); + out_be32((void *)(regs_win + offset), data); + + return 0; +} + +/** + * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction + * @index: ID of RapdiIO interface + * @destid: Destination ID of transaction + * @hopcount: Number of hops to target device + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @val: Location to be read into + * + * Generates a MPC85xx read maintenance transaction. Returns %0 on + * success or %-EINVAL on failure. + */ +static int +mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 * val) +{ + u8 *data; + + pr_debug + ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n", + index, destid, hopcount, offset, len); + out_be32((void *)&maint_atmu_regs->rowtar, + (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); + + data = (u8 *) maint_win + offset; + switch (len) { + case 1: + *val = in_8((u8 *) data); + break; + case 2: + *val = in_be16((u16 *) data); + break; + default: + *val = in_be32((u32 *) data); + break; + } + + return 0; +} + +/** + * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction + * @index: ID of RapdiIO interface + * @destid: Destination ID of transaction + * @hopcount: Number of hops to target device + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @val: Value to be written + * + * Generates an MPC85xx write maintenance transaction. Returns %0 on + * success or %-EINVAL on failure. + */ +static int +mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset, + int len, u32 val) +{ + u8 *data; + pr_debug + ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", + index, destid, hopcount, offset, len, val); + out_be32((void *)&maint_atmu_regs->rowtar, + (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); + + data = (u8 *) maint_win + offset; + switch (len) { + case 1: + out_8((u8 *) data, val); + break; + case 2: + out_be16((u16 *) data, val); + break; + default: + out_be32((u32 *) data, val); + break; + } + + return 0; +} + +/** + * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue + * @mport: Master port with outbound message queue + * @rdev: Target of outbound message + * @mbox: Outbound mailbox + * @buffer: Message to add to outbound queue + * @len: Length of message + * + * Adds the @buffer message to the MPC85xx outbound message queue. Returns + * %0 on success or %-EINVAL on failure. + */ +int +rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, + void *buffer, size_t len) +{ + u32 omr; + struct rio_tx_desc *desc = + (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot; + int ret = 0; + + pr_debug + ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n", + rdev->destid, mbox, (int)buffer, len); + + if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { + ret = -EINVAL; + goto out; + } + + /* Copy and clear rest of buffer */ + memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len); + if (len < (RIO_MAX_MSG_SIZE - 4)) + memset((void *)((u32) msg_tx_ring. + virt_buffer[msg_tx_ring.tx_slot] + len), 0, + RIO_MAX_MSG_SIZE - len); + + /* Set mbox field for message */ + desc->dport = mbox & 0x3; + + /* Enable EOMI interrupt, set priority, and set destid */ + desc->dattr = 0x28000000 | (rdev->destid << 2); + + /* Set transfer size aligned to next power of 2 (in double words) */ + desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); + + /* Set snooping and source buffer address */ + desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot]; + + /* Increment enqueue pointer */ + omr = in_be32((void *)&msg_regs->omr); + out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI); + + /* Go to next descriptor */ + if (++msg_tx_ring.tx_slot == msg_tx_ring.size) + msg_tx_ring.tx_slot = 0; + + out: + return ret; +} + +EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); + +/** + * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler + * @irq: Linux interrupt number + * @dev_instance: Pointer to interrupt-specific data + * @regs: Register context + * + * Handles outbound message interrupts. Executes a register outbound + * mailbox event handler and acks the interrupt occurence. + */ +static irqreturn_t +mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) +{ + int osr; + struct rio_mport *port = (struct rio_mport *)dev_instance; + + osr = in_be32((void *)&msg_regs->osr); + + if (osr & RIO_MSG_OSR_TE) { + pr_info("RIO: outbound message transmission error\n"); + out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE); + goto out; + } + + if (osr & RIO_MSG_OSR_QOI) { + pr_info("RIO: outbound message queue overflow\n"); + out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI); + goto out; + } + + if (osr & RIO_MSG_OSR_EOMI) { + u32 dqp = in_be32((void *)&msg_regs->odqdpar); + int slot = (dqp - msg_tx_ring.phys) >> 5; + port->outb_msg[0].mcback(port, -1, slot); + + /* Ack the end-of-message interrupt */ + out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI); + } + + out: + return IRQ_HANDLED; +} + +/** + * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox + * @mport: Master port implementing the outbound message unit + * @mbox: Mailbox to open + * @entries: Number of entries in the outbound mailbox ring + * + * Initializes buffer ring, request the outbound message interrupt, + * and enables the outbound message unit. Returns %0 on success and + * %-EINVAL or %-ENOMEM on failure. + */ +int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) +{ + int i, j, rc = 0; + + if ((entries < RIO_MIN_TX_RING_SIZE) || + (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) { + rc = -EINVAL; + goto out; + } + + /* Initialize shadow copy ring */ + msg_tx_ring.size = entries; + + for (i = 0; i < msg_tx_ring.size; i++) { + if (! + (msg_tx_ring.virt_buffer[i] = + dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE, + &msg_tx_ring.phys_buffer[i], + GFP_KERNEL))) { + rc = -ENOMEM; + for (j = 0; j < msg_tx_ring.size; j++) + if (msg_tx_ring.virt_buffer[j]) + dma_free_coherent(NULL, + RIO_MSG_BUFFER_SIZE, + msg_tx_ring. + virt_buffer[j], + msg_tx_ring. + phys_buffer[j]); + goto out; + } + } + + /* Initialize outbound message descriptor ring */ + if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL, + msg_tx_ring.size * + RIO_MSG_DESC_SIZE, + &msg_tx_ring.phys, + GFP_KERNEL))) { + rc = -ENOMEM; + goto out_dma; + } + memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE); + msg_tx_ring.tx_slot = 0; + + /* Point dequeue/enqueue pointers at first entry in ring */ + out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys); + out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys); + + /* Configure for snooping */ + out_be32((void *)&msg_regs->osar, 0x00000004); + + /* Clear interrupt status */ + out_be32((void *)&msg_regs->osr, 0x000000b3); + + /* Hook up outbound message handler */ + if ((rc = + request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0, + "msg_tx", (void *)mport)) < 0) + goto out_irq; + + /* + * Configure outbound message unit + * Snooping + * Interrupts (all enabled, except QEIE) + * Chaining mode + * Disable + */ + out_be32((void *)&msg_regs->omr, 0x00100220); + + /* Set number of entries */ + out_be32((void *)&msg_regs->omr, + in_be32((void *)&msg_regs->omr) | + ((get_bitmask_order(entries) - 2) << 12)); + + /* Now enable the unit */ + out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1); + + out: + return rc; + + out_irq: + dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE, + msg_tx_ring.virt, msg_tx_ring.phys); + + out_dma: + for (i = 0; i < msg_tx_ring.size; i++) + dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE, + msg_tx_ring.virt_buffer[i], + msg_tx_ring.phys_buffer[i]); + + return rc; +} + +/** + * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox + * @mport: Master port implementing the outbound message unit + * @mbox: Mailbox to close + * + * Disables the outbound message unit, free all buffers, and + * frees the outbound message interrupt. + */ +void rio_close_outb_mbox(struct rio_mport *mport, int mbox) +{ + /* Disable inbound message unit */ + out_be32((void *)&msg_regs->omr, 0); + + /* Free ring */ + dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE, + msg_tx_ring.virt, msg_tx_ring.phys); + + /* Free interrupt */ + free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport); +} + +/** + * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler + * @irq: Linux interrupt number + * @dev_instance: Pointer to interrupt-specific data + * @regs: Register context + * + * Handles inbound message interrupts. Executes a registered inbound + * mailbox event handler and acks the interrupt occurence. + */ +static irqreturn_t +mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) +{ + int isr; + struct rio_mport *port = (struct rio_mport *)dev_instance; + + isr = in_be32((void *)&msg_regs->isr); + + if (isr & RIO_MSG_ISR_TE) { + pr_info("RIO: inbound message reception error\n"); + out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE); + goto out; + } + + /* XXX Need to check/dispatch until queue empty */ + if (isr & RIO_MSG_ISR_DIQI) { + /* + * We implement *only* mailbox 0, but can receive messages + * for any mailbox/letter to that mailbox destination. So, + * make the callback with an unknown/invalid mailbox number + * argument. + */ + port->inb_msg[0].mcback(port, -1, -1); + + /* Ack the queueing interrupt */ + out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI); + } + + out: + return IRQ_HANDLED; +} + +/** + * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox + * @mport: Master port implementing the inbound message unit + * @mbox: Mailbox to open + * @entries: Number of entries in the inbound mailbox ring + * + * Initializes buffer ring, request the inbound message interrupt, + * and enables the inbound message unit. Returns %0 on success + * and %-EINVAL or %-ENOMEM on failure. + */ +int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) +{ + int i, rc = 0; + + if ((entries < RIO_MIN_RX_RING_SIZE) || + (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) { + rc = -EINVAL; + goto out; + } + + /* Initialize client buffer ring */ + msg_rx_ring.size = entries; + msg_rx_ring.rx_slot = 0; + for (i = 0; i < msg_rx_ring.size; i++) + msg_rx_ring.virt_buffer[i] = NULL; + + /* Initialize inbound message ring */ + if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL, + msg_rx_ring.size * + RIO_MAX_MSG_SIZE, + &msg_rx_ring.phys, + GFP_KERNEL))) { + rc = -ENOMEM; + goto out; + } + + /* Point dequeue/enqueue pointers at first entry in ring */ + out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys); + out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys); + + /* Clear interrupt status */ + out_be32((void *)&msg_regs->isr, 0x00000091); + + /* Hook up inbound message handler */ + if ((rc = + request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0, + "msg_rx", (void *)mport)) < 0) { + dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE, + msg_tx_ring.virt_buffer[i], + msg_tx_ring.phys_buffer[i]); + goto out; + } + + /* + * Configure inbound message unit: + * Snooping + * 4KB max message size + * Unmask all interrupt sources + * Disable + */ + out_be32((void *)&msg_regs->imr, 0x001b0060); + + /* Set number of queue entries */ + out_be32((void *)&msg_regs->imr, + in_be32((void *)&msg_regs->imr) | + ((get_bitmask_order(entries) - 2) << 12)); + + /* Now enable the unit */ + out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1); + + out: + return rc; +} + +/** + * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox + * @mport: Master port implementing the inbound message unit + * @mbox: Mailbox to close + * + * Disables the inbound message unit, free all buffers, and + * frees the inbound message interrupt. + */ +void rio_close_inb_mbox(struct rio_mport *mport, int mbox) +{ + /* Disable inbound message unit */ + out_be32((void *)&msg_regs->imr, 0); + + /* Free ring */ + dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE, + msg_rx_ring.virt, msg_rx_ring.phys); + + /* Free interrupt */ + free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport); +} + +/** + * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue + * @mport: Master port implementing the inbound message unit + * @mbox: Inbound mailbox number + * @buf: Buffer to add to inbound queue + * + * Adds the @buf buffer to the MPC85xx inbound message queue. Returns + * %0 on success or %-EINVAL on failure. + */ +int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) +{ + int rc = 0; + + pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", + msg_rx_ring.rx_slot); + + if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) { + printk(KERN_ERR + "RIO: error adding inbound buffer %d, buffer exists\n", + msg_rx_ring.rx_slot); + rc = -EINVAL; + goto out; + } + + msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf; + if (++msg_rx_ring.rx_slot == msg_rx_ring.size) + msg_rx_ring.rx_slot = 0; + + out: + return rc; +} + +EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer); + +/** + * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit + * @mport: Master port implementing the inbound message unit + * @mbox: Inbound mailbox number + * + * Gets the next available inbound message from the inbound message queue. + * A pointer to the message is returned on success or NULL on failure. + */ +void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) +{ + u32 imr; + u32 phys_buf, virt_buf; + void *buf = NULL; + int buf_idx; + + phys_buf = in_be32((void *)&msg_regs->ifqdpar); + + /* If no more messages, then bail out */ + if (phys_buf == in_be32((void *)&msg_regs->ifqepar)) + goto out2; + + virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys); + buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE; + buf = msg_rx_ring.virt_buffer[buf_idx]; + + if (!buf) { + printk(KERN_ERR + "RIO: inbound message copy failed, no buffers\n"); + goto out1; + } + + /* Copy max message size, caller is expected to allocate that big */ + memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE); + + /* Clear the available buffer */ + msg_rx_ring.virt_buffer[buf_idx] = NULL; + + out1: + imr = in_be32((void *)&msg_regs->imr); + out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI); + + out2: + return buf; +} + +EXPORT_SYMBOL_GPL(rio_hw_get_inb_message); + +/** + * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler + * @irq: Linux interrupt number + * @dev_instance: Pointer to interrupt-specific data + * @regs: Register context + * + * Handles doorbell interrupts. Parses a list of registered + * doorbell event handlers and executes a matching event handler. + */ +static irqreturn_t +mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs) +{ + int dsr; + struct rio_mport *port = (struct rio_mport *)dev_instance; + + dsr = in_be32((void *)&msg_regs->dsr); + + if (dsr & DOORBELL_DSR_TE) { + pr_info("RIO: doorbell reception error\n"); + out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE); + goto out; + } + + if (dsr & DOORBELL_DSR_QFI) { + pr_info("RIO: doorbell queue full\n"); + out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI); + goto out; + } + + /* XXX Need to check/dispatch until queue empty */ + if (dsr & DOORBELL_DSR_DIQI) { + u32 dmsg = + (u32) dbell_ring.virt + + (in_be32((void *)&msg_regs->dqdpar) & 0xfff); + u32 dmr; + struct rio_dbell *dbell; + int found = 0; + + pr_debug + ("RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x\n", + DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); + + list_for_each_entry(dbell, &port->dbells, node) { + if ((dbell->res->start <= DBELL_INF(dmsg)) && + (dbell->res->end >= DBELL_INF(dmsg))) { + found = 1; + break; + } + } + if (found) { + dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg), + DBELL_INF(dmsg)); + } else { + pr_debug + ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n", + DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); + } + dmr = in_be32((void *)&msg_regs->dmr); + out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI); + out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI); + } + + out: + return IRQ_HANDLED; +} + +/** + * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init + * @mport: Master port implementing the inbound doorbell unit + * + * Initializes doorbell unit hardware and inbound DMA buffer + * ring. Called from mpc85xx_rio_setup(). Returns %0 on success + * or %-ENOMEM on failure. + */ +static int mpc85xx_rio_doorbell_init(struct rio_mport *mport) +{ + int rc = 0; + + /* Map outbound doorbell window immediately after maintenance window */ + if (!(dbell_win = + (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE, + RIO_DBELL_WIN_SIZE))) { + printk(KERN_ERR + "RIO: unable to map outbound doorbell window\n"); + rc = -ENOMEM; + goto out; + } + + /* Initialize inbound doorbells */ + if (!(dbell_ring.virt = dma_alloc_coherent(NULL, + 512 * DOORBELL_MESSAGE_SIZE, + &dbell_ring.phys, + GFP_KERNEL))) { + printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n"); + rc = -ENOMEM; + iounmap((void *)dbell_win); + goto out; + } + + /* Point dequeue/enqueue pointers at first entry in ring */ + out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys); + out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys); + + /* Clear interrupt status */ + out_be32((void *)&msg_regs->dsr, 0x00000091); + + /* Hook up doorbell handler */ + if ((rc = + request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0, + "dbell_rx", (void *)mport) < 0)) { + iounmap((void *)dbell_win); + dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE, + dbell_ring.virt, dbell_ring.phys); + printk(KERN_ERR + "MPC85xx RIO: unable to request inbound doorbell irq"); + goto out; + } + + /* Configure doorbells for snooping, 512 entries, and enable */ + out_be32((void *)&msg_regs->dmr, 0x00108161); + + out: + return rc; +} + +static char *cmdline = NULL; + +static int mpc85xx_rio_get_hdid(int index) +{ + /* XXX Need to parse multiple entries in some format */ + if (!cmdline) + return -1; + + return simple_strtol(cmdline, NULL, 0); +} + +static int mpc85xx_rio_get_cmdline(char *s) +{ + if (!s) + return 0; + + cmdline = s; + return 1; +} + +__setup("riohdid=", mpc85xx_rio_get_cmdline); + +/** + * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface + * @law_start: Starting physical address of RapidIO LAW + * @law_size: Size of RapidIO LAW + * + * Initializes MPC85xx RapidIO hardware interface, configures + * master port with system-specific info, and registers the + * master port with the RapidIO subsystem. + */ +void mpc85xx_rio_setup(int law_start, int law_size) +{ + struct rio_ops *ops; + struct rio_mport *port; + + ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL); + ops->lcread = mpc85xx_local_config_read; + ops->lcwrite = mpc85xx_local_config_write; + ops->cread = mpc85xx_rio_config_read; + ops->cwrite = mpc85xx_rio_config_write; + ops->dsend = mpc85xx_rio_doorbell_send; + + port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL); + port->id = 0; + port->index = 0; + INIT_LIST_HEAD(&port->dbells); + port->iores.start = law_start; + port->iores.end = law_start + law_size; + port->iores.flags = IORESOURCE_MEM; + + rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); + rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0); + rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); + strcpy(port->name, "RIO0 mport"); + + port->ops = ops; + port->host_deviceid = mpc85xx_rio_get_hdid(port->id); + + rio_register_mport(port); + + regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000); + atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET); + maint_atmu_regs = atmu_regs + 1; + dbell_atmu_regs = atmu_regs + 2; + msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET); + + /* Configure maintenance transaction window */ + out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000); + out_be32((void *)&maint_atmu_regs->rowar, 0x80077015); + + maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE); + + /* Configure outbound doorbell window */ + out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400); + out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b); + mpc85xx_rio_doorbell_init(port); +} diff --git a/arch/ppc/syslib/ppc85xx_rio.h b/arch/ppc/syslib/ppc85xx_rio.h new file mode 100644 index 000000000000..c0827a2c3eec --- /dev/null +++ b/arch/ppc/syslib/ppc85xx_rio.h @@ -0,0 +1,21 @@ +/* + * MPC85xx RapidIO definitions + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef __PPC_SYSLIB_PPC85XX_RIO_H +#define __PPC_SYSLIB_PPC85XX_RIO_H + +#include +#include + +extern void mpc85xx_rio_setup(int law_start, int law_size); + +#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */ diff --git a/include/asm-ppc/rio.h b/include/asm-ppc/rio.h new file mode 100644 index 000000000000..0018bf80cb25 --- /dev/null +++ b/include/asm-ppc/rio.h @@ -0,0 +1,18 @@ +/* + * RapidIO architecture support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef ASM_PPC_RIO_H +#define ASM_PPC_RIO_H + +extern void platform_rio_init(void); + +#endif /* ASM_PPC_RIO_H */ -- cgit v1.2.3 From 6978bbc097c2f665c336927a9d56ae39ef75fa56 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:20 -0800 Subject: [PATCH] rapidio: message interface updates Updates the RIO messaging interface to pass a device instance into the event registeration and callbacks. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ppc85xx_rio.c | 16 +++++++++++----- drivers/rapidio/rio-sysfs.c | 4 ++-- drivers/rapidio/rio.c | 25 ++++++++++++++++--------- include/linux/rio.h | 10 ++++++---- include/linux/rio_drv.h | 12 ++++++------ 5 files changed, 41 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c index 9d09c2715e0a..297f3b549177 100644 --- a/arch/ppc/syslib/ppc85xx_rio.c +++ b/arch/ppc/syslib/ppc85xx_rio.c @@ -135,6 +135,7 @@ static struct rio_msg_tx_ring { dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE]; int tx_slot; int size; + void *dev_id; } msg_tx_ring; static struct rio_msg_rx_ring { @@ -143,6 +144,7 @@ static struct rio_msg_rx_ring { void *virt_buffer[RIO_MAX_RX_RING_SIZE]; int rx_slot; int size; + void *dev_id; } msg_rx_ring; /** @@ -376,7 +378,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) if (osr & RIO_MSG_OSR_EOMI) { u32 dqp = in_be32((void *)&msg_regs->odqdpar); int slot = (dqp - msg_tx_ring.phys) >> 5; - port->outb_msg[0].mcback(port, -1, slot); + port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot); /* Ack the end-of-message interrupt */ out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI); @@ -389,6 +391,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) /** * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open * @entries: Number of entries in the outbound mailbox ring * @@ -396,7 +399,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) * and enables the outbound message unit. Returns %0 on success and * %-EINVAL or %-ENOMEM on failure. */ -int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) +int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, j, rc = 0; @@ -407,6 +410,7 @@ int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) } /* Initialize shadow copy ring */ + msg_tx_ring.dev_id = dev_id; msg_tx_ring.size = entries; for (i = 0; i < msg_tx_ring.size; i++) { @@ -541,7 +545,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) * make the callback with an unknown/invalid mailbox number * argument. */ - port->inb_msg[0].mcback(port, -1, -1); + port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1); /* Ack the queueing interrupt */ out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI); @@ -554,6 +558,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) /** * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open * @entries: Number of entries in the inbound mailbox ring * @@ -561,7 +566,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) * and enables the inbound message unit. Returns %0 on success * and %-EINVAL or %-ENOMEM on failure. */ -int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) +int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, rc = 0; @@ -572,6 +577,7 @@ int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) } /* Initialize client buffer ring */ + msg_rx_ring.dev_id = dev_id; msg_rx_ring.size = entries; msg_rx_ring.rx_slot = 0; for (i = 0; i < msg_rx_ring.size; i++) @@ -777,7 +783,7 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs) } } if (found) { - dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg), + dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); } else { pr_debug diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 73218a37506d..30a11436e241 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -21,7 +21,7 @@ /* Sysfs support */ #define rio_config_attr(field, format_string) \ static ssize_t \ - field##_show(struct device *dev, char *buf) \ +field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct rio_dev *rdev = to_rio_dev(dev); \ \ @@ -35,7 +35,7 @@ rio_config_attr(asm_did, "0x%04x\n"); rio_config_attr(asm_vid, "0x%04x\n"); rio_config_attr(asm_rev, "0x%04x\n"); -static ssize_t routes_show(struct device *dev, char *buf) +static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rio_dev *rdev = to_rio_dev(dev); char *str = buf; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index adc299e2b07e..3ca1011ceaac 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -48,6 +48,7 @@ u16 rio_local_get_device_id(struct rio_mport *port) /** * rio_request_inb_mbox - request inbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in inbound mailbox queue * @minb: Callback to execute when inbound message is received @@ -56,9 +57,10 @@ u16 rio_local_get_device_id(struct rio_mport *port) * a callback function to the resource. Returns %0 on success. */ int rio_request_inb_mbox(struct rio_mport *mport, + void *dev_id, int mbox, int entries, - void (*minb) (struct rio_mport * mport, int mbox, + void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { int rc = 0; @@ -81,7 +83,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, /* Hook the inbound message callback */ mport->inb_msg[mbox].mcback = minb; - rc = rio_open_inb_mbox(mport, mbox, entries); + rc = rio_open_inb_mbox(mport, dev_id, mbox, entries); } else rc = -ENOMEM; @@ -108,6 +110,7 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) /** * rio_request_outb_mbox - request outbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in outbound mailbox queue * @moutb: Callback to execute when outbound message is sent @@ -116,10 +119,10 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) * a callback function to the resource. Returns 0 on success. */ int rio_request_outb_mbox(struct rio_mport *mport, + void *dev_id, int mbox, int entries, - void (*moutb) (struct rio_mport * mport, int mbox, - int slot)) + void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { int rc = 0; @@ -141,7 +144,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, /* Hook the inbound message callback */ mport->outb_msg[mbox].mcback = moutb; - rc = rio_open_outb_mbox(mport, mbox, entries); + rc = rio_open_outb_mbox(mport, dev_id, mbox, entries); } else rc = -ENOMEM; @@ -168,6 +171,7 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) /** * rio_setup_inb_dbell - bind inbound doorbell callback * @mport: RIO master port to bind the doorbell callback + * @dev_id: Device specific pointer to pass on event * @res: Doorbell message resource * @dinb: Callback to execute when doorbell is received * @@ -176,8 +180,8 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) * satisfied. */ static int -rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, - void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, +rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res, + void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { int rc = 0; @@ -190,6 +194,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, dbell->res = res; dbell->dinb = dinb; + dbell->dev_id = dev_id; list_add_tail(&dbell->node, &mport->dbells); @@ -200,6 +205,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, /** * rio_request_inb_dbell - request inbound doorbell message service * @mport: RIO master port from which to allocate the doorbell resource + * @dev_id: Device specific pointer to pass on event * @start: Doorbell info range start * @end: Doorbell info range end * @dinb: Callback to execute when doorbell is received @@ -209,9 +215,10 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, * has been satisfied. */ int rio_request_inb_dbell(struct rio_mport *mport, + void *dev_id, u16 start, u16 end, - void (*dinb) (struct rio_mport * mport, u16 src, + void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { int rc = 0; @@ -230,7 +237,7 @@ int rio_request_inb_dbell(struct rio_mport *mport, } /* Hook the doorbell callback */ - rc = rio_setup_inb_dbell(mport, res, dinb); + rc = rio_setup_inb_dbell(mport, dev_id, res, dinb); } else rc = -ENOMEM; diff --git a/include/linux/rio.h b/include/linux/rio.h index 5c29f2f477c2..c7e907faae9c 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -132,7 +132,7 @@ struct rio_dev { */ struct rio_msg { struct resource *res; - void (*mcback) (struct rio_mport * mport, int mbox, int slot); + void (*mcback) (struct rio_mport * mport, void *dev_id, int mbox, int slot); }; /** @@ -140,11 +140,13 @@ struct rio_msg { * @node: Node in list of doorbell events * @res: Doorbell resource * @dinb: Doorbell event callback + * @dev_id: Device specific pointer to pass on event */ struct rio_dbell { struct list_head node; struct resource *res; - void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, u16 info); + void (*dinb) (struct rio_mport *mport, void *dev_id, u16 src, u16 dst, u16 info); + void *dev_id; }; /** @@ -314,9 +316,9 @@ extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int, void *, size_t); extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *); extern void *rio_hw_get_inb_message(struct rio_mport *, int); -extern int rio_open_inb_mbox(struct rio_mport *, int, int); +extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_inb_mbox(struct rio_mport *, int); -extern int rio_open_outb_mbox(struct rio_mport *, int, int); +extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_outb_mbox(struct rio_mport *, int); #endif /* __KERNEL__ */ diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h index 7483dfc0dfa3..3bd7cce19e26 100644 --- a/include/linux/rio_drv.h +++ b/include/linux/rio_drv.h @@ -348,8 +348,8 @@ static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID /* Mailbox management */ -extern int rio_request_outb_mbox(struct rio_mport *, int, int, - void (*)(struct rio_mport *, int, int)); +extern int rio_request_outb_mbox(struct rio_mport *, void *, int, int, + void (*)(struct rio_mport *, void *,int, int)); extern int rio_release_outb_mbox(struct rio_mport *, int); /** @@ -370,8 +370,8 @@ static inline int rio_add_outb_message(struct rio_mport *mport, return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len); } -extern int rio_request_inb_mbox(struct rio_mport *, int, int, - void (*)(struct rio_mport *, int, int)); +extern int rio_request_inb_mbox(struct rio_mport *, void *, int, int, + void (*)(struct rio_mport *, void *, int, int)); extern int rio_release_inb_mbox(struct rio_mport *, int); /** @@ -403,8 +403,8 @@ static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) } /* Doorbell management */ -extern int rio_request_inb_dbell(struct rio_mport *, u16, u16, - void (*)(struct rio_mport *, u16, u16, u16)); +extern int rio_request_inb_dbell(struct rio_mport *, void *, u16, u16, + void (*)(struct rio_mport *, void *, u16, u16, u16)); extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); -- cgit v1.2.3 From 70c3b76c28b012452d63bb27f6d0517afb05d86f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:25 -0800 Subject: [PATCH] knfsd: Allow run-time selection of NFS versions to export Provide a file in the NFSD filesystem that allows setting and querying of which version of NFS are being exported. Changes are only allowed while no server is running. Signed-off-by: Steve Dickson Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfsctl.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 79 +++++++++++++++++++++++++++--------------- include/linux/nfsd/nfsd.h | 2 +- include/linux/nfsd/syscall.h | 17 +++++++++ 4 files changed, 151 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 2a99a0bf54f6..a0871b3efeb7 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #include +unsigned int nfsd_versbits = ~0; + /* * We have a single directory with 9 nodes in it. */ @@ -50,8 +53,15 @@ enum { NFSD_List, NFSD_Fh, NFSD_Threads, + NFSD_Versions, + /* + * The below MUST come last. Otherwise we leave a hole in nfsd_files[] + * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops + */ +#ifdef CONFIG_NFSD_V4 NFSD_Leasetime, NFSD_RecoveryDir, +#endif }; /* @@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size); static ssize_t write_getfs(struct file *file, char *buf, size_t size); static ssize_t write_filehandle(struct file *file, char *buf, size_t size); static ssize_t write_threads(struct file *file, char *buf, size_t size); +static ssize_t write_versions(struct file *file, char *buf, size_t size); +#ifdef CONFIG_NFSD_V4 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); +#endif static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Svc] = write_svc, @@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Getfs] = write_getfs, [NFSD_Fh] = write_filehandle, [NFSD_Threads] = write_threads, + [NFSD_Versions] = write_versions, +#ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = write_leasetime, [NFSD_RecoveryDir] = write_recoverydir, +#endif }; static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -343,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return strlen(buf); } +static ssize_t write_versions(struct file *file, char *buf, size_t size) +{ + /* + * Format: + * [-/+]vers [-/+]vers ... + */ + char *mesg = buf; + char *vers, sign; + int len, num; + ssize_t tlen = 0; + char *sep; + + if (size>0) { + if (nfsd_serv) + return -EBUSY; + if (buf[size-1] != '\n') + return -EINVAL; + buf[size-1] = 0; + + vers = mesg; + len = qword_get(&mesg, vers, size); + if (len <= 0) return -EINVAL; + do { + sign = *vers; + if (sign == '+' || sign == '-') + num = simple_strtol((vers+1), NULL, 0); + else + num = simple_strtol(vers, NULL, 0); + switch(num) { + case 2: + case 3: + case 4: + if (sign != '-') + NFSCTL_VERSET(nfsd_versbits, num); + else + NFSCTL_VERUNSET(nfsd_versbits, num); + break; + default: + return -EINVAL; + } + vers += len + 1; + tlen += len; + } while ((len = qword_get(&mesg, vers, size)) > 0); + /* If all get turned off, turn them back on, as + * having no versions is BAD + */ + if ((nfsd_versbits & NFSCTL_VERALL)==0) + nfsd_versbits = NFSCTL_VERALL; + } + /* Now write current state into reply buffer */ + len = 0; + sep = ""; + for (num=2 ; num <= 4 ; num++) + if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) { + len += sprintf(buf+len, "%s%c%d", sep, + NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-', + num); + sep = " "; + } + len += sprintf(buf+len, "\n"); + return len; +} + +#ifdef CONFIG_NFSD_V4 extern time_t nfs4_leasetime(void); static ssize_t write_leasetime(struct file *file, char *buf, size_t size) @@ -384,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) status = nfs4_reset_recoverydir(recdir); return strlen(buf); } +#endif /*----------------------------------------------------------------------------*/ /* @@ -403,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 1697539a7171..0568ff8565b1 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ extern struct svc_program nfsd_program; static void nfsd(struct svc_rqst *rqstp); struct timeval nfssvc_boot; -static struct svc_serv *nfsd_serv; + struct svc_serv *nfsd_serv; static atomic_t nfsd_busy; static unsigned long nfsd_last_call; static DEFINE_SPINLOCK(nfsd_call_lock); @@ -63,6 +64,31 @@ struct nfsd_list { }; static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list); +static struct svc_version * nfsd_version[] = { + [2] = &nfsd_version2, +#if defined(CONFIG_NFSD_V3) + [3] = &nfsd_version3, +#endif +#if defined(CONFIG_NFSD_V4) + [4] = &nfsd_version4, +#endif +}; + +#define NFSD_MINVERS 2 +#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) +static struct svc_version *nfsd_versions[NFSD_NRVERS]; + +struct svc_program nfsd_program = { + .pg_prog = NFS_PROGRAM, /* program number */ + .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ + .pg_vers = nfsd_versions, /* version table */ + .pg_name = "nfsd", /* program name */ + .pg_class = "nfsd", /* authentication class */ + .pg_stats = &nfsd_svcstats, /* version table */ + .pg_authenticate = &svc_set_client, /* export authentication */ + +}; + /* * Maximum number of nfsd processes */ @@ -80,11 +106,12 @@ int nfsd_svc(unsigned short port, int nrservs) { int error; - int none_left; + int none_left, found_one, i; struct list_head *victim; lock_kernel(); - dprintk("nfsd: creating service\n"); + dprintk("nfsd: creating service: vers 0x%x\n", + nfsd_versbits); error = -EINVAL; if (nrservs <= 0) nrservs = 0; @@ -99,6 +126,27 @@ nfsd_svc(unsigned short port, int nrservs) if (error<0) goto out; if (!nfsd_serv) { + /* + * Use the nfsd_ctlbits to define which + * versions that will be advertised. + * If nfsd_ctlbits doesn't list any version, + * export them all. + */ + found_one = 0; + + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { + if (NFSCTL_VERISSET(nfsd_versbits, i)) { + nfsd_program.pg_vers[i] = nfsd_version[i]; + found_one = 1; + } else + nfsd_program.pg_vers[i] = NULL; + } + + if (!found_one) { + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) + nfsd_program.pg_vers[i] = nfsd_version[i]; + } + atomic_set(&nfsd_busy, 0); error = -ENOMEM; nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); @@ -389,28 +437,3 @@ static struct svc_stat nfsd_acl_svcstats = { #else #define nfsd_acl_program_p NULL #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ - -extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - -static struct svc_version * nfsd_version[] = { - [2] = &nfsd_version2, -#if defined(CONFIG_NFSD_V3) - [3] = &nfsd_version3, -#endif -#if defined(CONFIG_NFSD_V4) - [4] = &nfsd_version4, -#endif -}; - -#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) -struct svc_program nfsd_program = { - .pg_next = nfsd_acl_program_p, - .pg_prog = NFS_PROGRAM, /* program number */ - .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ - .pg_vers = nfsd_version, /* version table */ - .pg_name = "nfsd", /* program name */ - .pg_class = "nfsd", /* authentication class */ - .pg_stats = &nfsd_svcstats, /* version table */ - .pg_authenticate = &svc_set_client, /* export authentication */ - -}; diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 6d5a24f3fc6d..51c231a1e5a6 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -60,7 +60,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); extern struct svc_program nfsd_program; extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - +extern struct svc_serv *nfsd_serv; /* * Function prototypes. */ diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h index e65c9db6d13f..781efbf94ed3 100644 --- a/include/linux/nfsd/syscall.h +++ b/include/linux/nfsd/syscall.h @@ -39,6 +39,21 @@ #define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ #define NFSCTL_GETFS 8 /* get an fh by path with max FH len */ +/* + * Macros used to set version + */ +#define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << (_v))) +#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v))) +#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v))) + +#if defined(CONFIG_NFSD_V4) +#define NFSCTL_VERALL (0x1c /* 0b011100 */) +#elif defined(CONFIG_NFSD_V3) +#define NFSCTL_VERALL (0x0c /* 0b001100 */) +#else +#define NFSCTL_VERALL (0x04 /* 0b000100 */) +#endif + /* SVC */ struct nfsctl_svc { unsigned short svc_port; @@ -120,6 +135,8 @@ extern int exp_delclient(struct nfsctl_client *ncp); extern int exp_export(struct nfsctl_export *nxp); extern int exp_unexport(struct nfsctl_export *nxp); +extern unsigned int nfsd_versbits; + #endif /* __KERNEL__ */ #endif /* NFSD_SYSCALL_H */ -- cgit v1.2.3 From 0ba7536d5d47e4ecf2259a80b207158dc4e711eb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:26 -0800 Subject: [PATCH] knfsd: Fix some minor sign problems in nfsd/xdr There are a couple of tests which could possibly be confused by extremely large numbers appearing in 'xdr' packets. I think the closest to an exploit you could get would be writing random data from a free page into a file - i.e. leak data out of kernel space. I'm fairly sure they cannot be used for remote compromise. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs3xdr.c | 3 ++- include/linux/nfsd/xdr3.h | 2 +- include/linux/sunrpc/svc.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e0e134d6baba..9147b8524d05 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, len = args->len = ntohl(*p++); hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; - if (rqstp->rq_arg.len < len + hdr) + if (rqstp->rq_arg.len < hdr || + rqstp->rq_arg.len - hdr < len) return 0; args->vec[0].iov_base = (void*)p; diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h index 21e18ce7ca63..3c2a71b43bac 100644 --- a/include/linux/nfsd/xdr3.h +++ b/include/linux/nfsd/xdr3.h @@ -42,7 +42,7 @@ struct nfsd3_writeargs { __u64 offset; __u32 count; int stable; - int len; + __u32 len; struct kvec vec[RPCSVC_MAXPAGES]; int vlen; }; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 5af8800e0ce3..e4086ec8b952 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -171,7 +171,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, u32 *p) { char *cp = (char *)p; struct kvec *vec = &rqstp->rq_arg.head[0]; - return cp - (char*)vec->iov_base <= vec->iov_len; + return cp >= (char*)vec->iov_base + && cp <= (char*)vec->iov_base + vec->iov_len; } static inline int -- cgit v1.2.3 From c465e05a03209651078b95686158648fd7ed84c5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:35 -0800 Subject: [PATCH] fbcon/fbdev: Move softcursor out of fbdev to fbcon According to Jon Smirl, filling in the field fb_cursor with soft_cursor for drivers that do not support hardware cursors is redundant. The soft_cursor function is usable by all drivers because it is just a wrapper around fb_imageblit. And because soft_cursor is an fbcon-specific hook, the file is moved to the console directory. Thus, drivers that do not support hardware cursors can leave the fb_cursor field blank. For drivers that do, they can fill up this field with their own version. The end result is a smaller code size. And if the framebuffer console is not loaded, module/kernel size is also reduced because the soft_cursor module will also not be loaded. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/68328fb.c | 1 - drivers/video/Kconfig | 79 ---------------------------------- drivers/video/Makefile | 1 - drivers/video/acornfb.c | 1 - drivers/video/amba-clcd.c | 1 - drivers/video/amifb.c | 1 - drivers/video/arcfb.c | 1 - drivers/video/asiliantfb.c | 1 - drivers/video/aty/aty128fb.c | 1 - drivers/video/aty/atyfb_base.c | 1 - drivers/video/aty/radeon_base.c | 1 - drivers/video/bw2.c | 1 - drivers/video/cg14.c | 1 - drivers/video/cg3.c | 1 - drivers/video/cg6.c | 1 - drivers/video/chipsfb.c | 1 - drivers/video/cirrusfb.c | 1 - drivers/video/clps711xfb.c | 1 - drivers/video/console/Makefile | 2 +- drivers/video/console/bitblit.c | 7 ++- drivers/video/console/fbcon.h | 2 +- drivers/video/console/softcursor.c | 72 +++++++++++++++++++++++++++++++ drivers/video/controlfb.c | 1 - drivers/video/cyber2000fb.c | 1 - drivers/video/cyblafb.c | 1 - drivers/video/dnfb.c | 1 - drivers/video/epson1355fb.c | 1 - drivers/video/ffb.c | 3 -- drivers/video/fm2fb.c | 1 - drivers/video/gbefb.c | 1 - drivers/video/geode/Kconfig | 1 - drivers/video/geode/gx1fb_core.c | 1 - drivers/video/hitfb.c | 1 - drivers/video/hpfb.c | 1 - drivers/video/imsttfb.c | 1 - drivers/video/imxfb.c | 1 - drivers/video/intelfb/intelfbdrv.c | 2 +- drivers/video/kyro/fbdev.c | 1 - drivers/video/leo.c | 1 - drivers/video/macfb.c | 1 - drivers/video/matrox/matroxfb_accel.c | 2 +- drivers/video/matrox/matroxfb_crtc2.c | 1 - drivers/video/maxinefb.c | 1 - drivers/video/neofb.c | 1 - drivers/video/nvidia/nvidia.c | 2 +- drivers/video/offb.c | 1 - drivers/video/p9100.c | 1 - drivers/video/platinumfb.c | 1 - drivers/video/pm2fb.c | 1 - drivers/video/pmag-ba-fb.c | 1 - drivers/video/pmagb-b-fb.c | 1 - drivers/video/pvr2fb.c | 1 - drivers/video/pxafb.c | 1 - drivers/video/q40fb.c | 1 - drivers/video/radeonfb.c | 1 - drivers/video/s1d13xxxfb.c | 1 - drivers/video/s3c2410fb.c | 1 - drivers/video/sa1100fb.c | 1 - drivers/video/savage/savagefb_driver.c | 1 - drivers/video/sgivwfb.c | 1 - drivers/video/sis/sis_main.c | 2 + drivers/video/skeletonfb.c | 9 ++-- drivers/video/softcursor.c | 72 ------------------------------- drivers/video/sstfb.c | 1 - drivers/video/stifb.c | 1 - drivers/video/tcx.c | 1 - drivers/video/tdfxfb.c | 1 - drivers/video/tgafb.c | 1 - drivers/video/tridentfb.c | 1 - drivers/video/tx3912fb.c | 1 - drivers/video/valkyriefb.c | 1 - drivers/video/vesafb.c | 1 - drivers/video/vfb.c | 1 - drivers/video/vga16fb.c | 1 - drivers/video/w100fb.c | 1 - include/linux/fb.h | 1 - 76 files changed, 88 insertions(+), 230 deletions(-) create mode 100644 drivers/video/console/softcursor.c delete mode 100644 drivers/video/softcursor.c (limited to 'include') diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 6a3cfbdc6dc9..3b0ddc55236b 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -113,7 +113,6 @@ static struct fb_ops mc68x328fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = mc68x328fb_mmap, }; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9c54695911c1..44b6ca290ce3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -65,15 +65,6 @@ config FB_CFB_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version. -config FB_SOFT_CURSOR - tristate - depends on FB - default n - ---help--- - Include the soft_cursor function for generic software cursor support. - This is used by drivers that don't provide their own (accelerated) - version. - config FB_MACMODES tristate depends on FB @@ -114,7 +105,6 @@ config FB_CIRRUS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This enables support for Cirrus Logic GD542x/543x based boards on Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. @@ -133,7 +123,6 @@ config FB_PM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -152,7 +141,6 @@ config FB_ARMCLCD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This framebuffer device driver is for the ARM PrimeCell PL110 Colour LCD controller. ARM PrimeCells provide the building @@ -169,7 +157,6 @@ config FB_ACORN select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Acorn VIDC graphics hardware found in Acorn RISC PCs and other ARM-based machines. If @@ -181,7 +168,6 @@ config FB_CLPS711X select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y to enable the Framebuffer driver for the CLPS7111 and EP7212 processors. @@ -192,7 +178,6 @@ config FB_SA1100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is a framebuffer device for the SA-1100 LCD Controller. See for information on framebuffer @@ -207,7 +192,6 @@ config FB_IMX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_CYBER2000 tristate "CyberPro 2000/2010/5000 support" @@ -215,7 +199,6 @@ config FB_CYBER2000 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Integraphics CyberPro 20x0 and 5000 VGA chips used in the Rebel.com Netwinder and other machines. @@ -228,7 +211,6 @@ config FB_APOLLO default y select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_Q40 bool @@ -237,12 +219,10 @@ config FB_Q40 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_AMIGA tristate "Amiga native chipset support" depends on FB && AMIGA - select FB_SOFT_CURSOR help This is the frame buffer device driver for the builtin graphics chipset found in Amigas. @@ -282,7 +262,6 @@ config FB_CYBER select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64 graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -297,7 +276,6 @@ config FB_VIRGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64/3D graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -320,7 +298,6 @@ config FB_FM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Amiga FrameMaster card from BSC (exhibited 1992 but not shipped as a CBM product). @@ -331,7 +308,6 @@ config FB_ARC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Arc Monochrome LCD board. The board is based on the KS-108 lcd controller and is typically a matrix @@ -354,7 +330,6 @@ config FB_OF select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help Say Y if you want support with Open Firmware for your graphics @@ -366,7 +341,6 @@ config FB_CONTROL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the graphics adapter in the @@ -378,7 +352,6 @@ config FB_PLATINUM select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "platinum" graphics @@ -390,7 +363,6 @@ config FB_VALKYRIE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "valkyrie" graphics @@ -402,7 +374,6 @@ config FB_CT65550 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Chips & Technologies 65550 graphics chip in PowerBooks. @@ -413,13 +384,11 @@ config FB_ASILIANT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_IMSTT bool "IMS Twin Turbo display support" depends on (FB = y) && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help The IMS Twin Turbo is a PCI-based frame buffer card bundled with @@ -431,7 +400,6 @@ config FB_VGA16 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for VGA 16 color graphic cards. Say Y if you have such a card. @@ -445,7 +413,6 @@ config FB_STI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y ---help--- STI refers to the HP "Standard Text Interface" which is a set of @@ -466,7 +433,6 @@ config FB_MAC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES # bool ' Apple DAFB display support' CONFIG_FB_DAFB @@ -475,7 +441,6 @@ config FB_HP300 depends on (FB = y) && HP300 select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y config FB_TGA @@ -484,7 +449,6 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. @@ -495,7 +459,6 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -513,7 +476,6 @@ config FB_HGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a Hercules mono graphics card. @@ -542,7 +504,6 @@ config FB_SGIVW select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help SGI Visual Workstation support for framebuffer graphics. @@ -552,7 +513,6 @@ config FB_GBE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for SGI Graphics Backend. This chip is used in SGI O2 and Visual Workstation 320/540. @@ -580,7 +540,6 @@ config FB_BW2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the BWtwo frame buffer. @@ -589,7 +548,6 @@ config FB_CG3 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGthree frame buffer. @@ -598,7 +556,6 @@ config FB_CG6 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGsix (GX, TurboGX) frame buffer. @@ -609,7 +566,6 @@ config FB_PVR2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a PowerVR 2 card in your box. If you plan to run linux on your Dreamcast, you will have to say Y here. @@ -631,7 +587,6 @@ config FB_EPSON1355 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Build in support for the SED1355 Epson Research Embedded RAMDAC LCD/CRT Controller (since redesignated as the S1D13505) as a @@ -676,7 +631,6 @@ config FB_S1D13XXX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for S1D13XXX framebuffer device family (currently only working with S1D13806). Product specs at @@ -691,7 +645,6 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -809,7 +762,6 @@ config FB_INTEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports the on-board graphics built in to the Intel 830M/845G/852GM/855GM/865G chipsets. @@ -832,7 +784,6 @@ config FB_MATROX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_TILEBLITTING select FB_MACMODES if PPC_PMAC ---help--- @@ -973,7 +924,6 @@ config FB_RADEON_OLD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help Choose this option if you want to use an ATI Radeon graphics card as @@ -991,7 +941,6 @@ config FB_RADEON select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_OF help Choose this option if you want to use an ATI Radeon graphics card as @@ -1029,7 +978,6 @@ config FB_ATY128 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_PMAC help This driver supports graphics boards with the ATI Rage128 chips. @@ -1045,7 +993,6 @@ config FB_ATY select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help This driver supports graphics boards with the ATI Mach64 chips. @@ -1103,7 +1050,6 @@ config FB_SAVAGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks and computers with S3 Savage PCI/AGP chips. @@ -1140,7 +1086,6 @@ config FB_SIS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SiS 300, 315, 330 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. @@ -1170,7 +1115,6 @@ config FB_NEOMAGIC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. @@ -1184,7 +1128,6 @@ config FB_KYRO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a STG4000 / Kyro / PowerVR 3 based graphics board. @@ -1198,7 +1141,6 @@ config FB_3DFX select FB_CFB_IMAGEBLIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA - select FB_SOFT_CURSOR help This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. Say Y if you have such a graphics board. @@ -1220,7 +1162,6 @@ config FB_VOODOO1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or Voodoo2 (cvg) based graphics card. @@ -1237,7 +1178,6 @@ config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select VIDEO_SELECT ---help--- This driver is supposed to support the Trident Cyberblade/i1 @@ -1265,7 +1205,6 @@ config FB_TRIDENT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This driver is supposed to support graphics boards with the Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops @@ -1314,7 +1253,6 @@ config FB_FFB depends on FB_SBUS && SPARC64 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Creator, Creator3D, and Elite3D graphics boards. @@ -1325,7 +1263,6 @@ config FB_TCX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the TCX 24/8bit frame buffer. @@ -1336,7 +1273,6 @@ config FB_CG14 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGfourteen frame buffer on Desktop SPARCsystems with the SX graphics option. @@ -1347,7 +1283,6 @@ config FB_P9100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the P9100 card supported on Sparcbook 3 machines. @@ -1358,7 +1293,6 @@ config FB_LEO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. @@ -1373,7 +1307,6 @@ config FB_IGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the framebuffer device for the INTERGRAPHICS 1680 and successor frame buffer cards. @@ -1384,7 +1317,6 @@ config FB_HIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Hitachi HD64461 LCD frame buffer card. @@ -1395,7 +1327,6 @@ config FB_PMAG_AA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) used mainly in the MIPS-based DECstation series. @@ -1406,7 +1337,6 @@ config FB_PMAG_BA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) used mainly in the MIPS-based DECstation series. @@ -1417,7 +1347,6 @@ config FB_PMAGB_B select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAGB-B TURBOchannel framebuffer card used mainly in the MIPS-based DECstation series. The card is currently only @@ -1429,7 +1358,6 @@ config FB_MAXINE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the onboard framebuffer (1024x768x8) in the Personal DECstation series (Personal DECstation 5000/20, /25, /33, /50, @@ -1441,7 +1369,6 @@ config FB_TX3912 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core see . @@ -1454,7 +1381,6 @@ config FB_G364 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The G364 driver is the framebuffer used in MIPS Magnum 4000 and Olivetti M700-10 systems. @@ -1465,7 +1391,6 @@ config FB_68328 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you want to support the built-in frame buffer of the Motorola 68328 CPU family. @@ -1476,7 +1401,6 @@ config FB_PXA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Intel PXA2x0 processor. @@ -1511,7 +1435,6 @@ config FB_W100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. @@ -1528,7 +1451,6 @@ config FB_S3C2410 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Samsung S3C2410 processor. @@ -1552,7 +1474,6 @@ config FB_VIRTUAL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This is a `virtual' frame buffer device. It operates on a chunk of unswappable kernel memory instead of on the memory of a graphics diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 97c5d03ac8d9..aa434e725c0d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,7 +16,6 @@ fb-objs := $(fb-y) obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o obj-$(CONFIG_FB_MACMODES) += macmodes.o # Hardware specific drivers go first diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 9b6a39348f81..193b482570c7 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -926,7 +926,6 @@ static struct fb_ops acornfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = acornfb_mmap, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 4fc93dc2b4d3..467a1d7ebbde 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -333,7 +333,6 @@ static struct fb_ops clcdfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = clcdfb_mmap, }; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index cf8bb67462dc..d549e215f3c5 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1185,7 +1185,6 @@ static struct fb_ops amifb_ops = { .fb_fillrect = amifb_fillrect, .fb_copyarea = amifb_copyarea, .fb_imageblit = amifb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = amifb_ioctl, }; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 6aa9f824c185..a1fc8bbb1090 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -511,7 +511,6 @@ static struct fb_ops arcfb_ops = { .fb_fillrect = arcfb_fillrect, .fb_copyarea = arcfb_copyarea, .fb_imageblit = arcfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = arcfb_ioctl, }; diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index f4729f4df8ce..c64de59398f4 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -106,7 +106,6 @@ static struct fb_ops asiliantfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Calculate the ratios for the dot clocks without using a single long long diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e380ee8b0247..e686185a076d 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -478,7 +478,6 @@ static struct fb_ops aty128fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PMAC_BACKLIGHT diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 037fe9d32fe3..5e4523ae85b1 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -292,7 +292,6 @@ static struct fb_ops atyfb_ops = { .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit, - .fb_cursor = soft_cursor, #ifdef __sparc__ .fb_mmap = atyfb_mmap, #endif diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 7ef4b901b93e..29f5b2cdbb7a 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1873,7 +1873,6 @@ static struct fb_ops radeonfb_ops = { .fb_fillrect = radeonfb_fillrect, .fb_copyarea = radeonfb_copyarea, .fb_imageblit = radeonfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 3d20b2d47d46..f53bf3ba1278 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -51,7 +51,6 @@ static struct fb_ops bw2_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = bw2_mmap, .fb_ioctl = bw2_ioctl, - .fb_cursor = soft_cursor, }; /* OBio addresses for the bwtwo registers */ diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 18e60b941e21..030d4b13b1c2 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -49,7 +49,6 @@ static struct fb_ops cg14_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg14_mmap, .fb_ioctl = cg14_ioctl, - .fb_cursor = soft_cursor, }; #define CG14_MCR_INTENABLE_SHIFT 7 diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 6e7d8d45dc68..b94eee8c42d5 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -50,7 +50,6 @@ static struct fb_ops cg3_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg3_mmap, .fb_ioctl = cg3_ioctl, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 49a2545671d9..3280bb9560e2 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -54,7 +54,6 @@ static struct fb_ops cg6_ops = { .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, .fb_ioctl = cg6_ioctl, - .fb_cursor = soft_cursor, }; /* Offset of interesting structures in the OBIO space */ diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 4131243cfdf8..bc061d4ec786 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -91,7 +91,6 @@ static struct fb_ops chipsfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int chipsfb_check_var(struct fb_var_screeninfo *var, diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 3a26f9cc8585..2858c5c8ba3c 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -548,7 +548,6 @@ static struct fb_ops cirrusfb_ops = { .fb_fillrect = cirrusfb_fillrect, .fb_copyarea = cirrusfb_copyarea, .fb_imageblit = cirrusfb_imageblit, - .fb_cursor = soft_cursor, }; /*--- Hardware Specific Routines -------------------------------------------*/ diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c index 8692e002986b..50b78af0fa24 100644 --- a/drivers/video/clps711xfb.c +++ b/drivers/video/clps711xfb.c @@ -219,7 +219,6 @@ static struct fb_ops clps7111fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 42c7b8dcd220..71b4b626e328 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 9f70e512b88b..67857b3cfc8b 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -272,6 +272,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1; char *src; cursor.set = 0; @@ -408,7 +409,11 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, cursor.image.depth = 1; cursor.rop = ROP_XOR; - info->fbops->fb_cursor(info, &cursor); + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); ops->cursor_reset = 0; } diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 0738cd62def2..b68e0e2c2d16 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -167,5 +167,5 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops); #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); - +extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); #endif /* _VIDEO_FBCON_H */ diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c new file mode 100644 index 000000000000..8529bf08db28 --- /dev/null +++ b/drivers/video/console/softcursor.c @@ -0,0 +1,72 @@ +/* + * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * + * Created 14 Nov 2002 by James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include + +#include +#include + +int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + unsigned int scan_align = info->pixmap.scan_align - 1; + unsigned int buf_align = info->pixmap.buf_align - 1; + unsigned int i, size, dsize, s_pitch, d_pitch; + struct fb_image *image; + u8 *dst, *src; + + if (info->state != FBINFO_STATE_RUNNING) + return 0; + + s_pitch = (cursor->image.width + 7) >> 3; + dsize = s_pitch * cursor->image.height; + + src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); + if (!src) + return -ENOMEM; + + image = (struct fb_image *) (src + dsize); + *image = cursor->image; + d_pitch = (s_pitch + scan_align) & ~scan_align; + + size = d_pitch * image->height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + + if (cursor->enable) { + switch (cursor->rop) { + case ROP_XOR: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] ^ cursor->mask[i]; + break; + case ROP_COPY: + default: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] & cursor->mask[i]; + break; + } + } else + memcpy(src, image->data, dsize); + + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); + image->data = dst; + info->fbops->fb_imageblit(info, image); + kfree(src); + return 0; +} + +EXPORT_SYMBOL(soft_cursor); + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Generic software cursor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 989e700159e0..403d17377f8d 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -176,7 +176,6 @@ static struct fb_ops controlfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 3894b2a501d6..c589d23e7f91 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1064,7 +1064,6 @@ static struct fb_ops cyber2000fb_ops = { .fb_fillrect = cyber2000fb_fillrect, .fb_copyarea = cyber2000fb_copyarea, .fb_imageblit = cyber2000fb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = cyber2000fb_sync, }; diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index 6992100a508c..03fbe83d71a8 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -968,7 +968,6 @@ static struct fb_ops cyblafb_ops __devinitdata = { .fb_fillrect = cyblafb_fillrect, .fb_copyarea= cyblafb_copyarea, .fb_imageblit = cyblafb_imageblit, - .fb_cursor = soft_cursor, }; //========================================================================== diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index 1785686a7f11..957a3ada2b75 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -116,7 +116,6 @@ static struct fb_ops dn_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = dnfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; struct fb_var_screeninfo dnfb_var __devinitdata = { diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 7363d0b25fdf..6a81a1dd8f3d 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -484,7 +484,6 @@ static struct fb_ops epson1355fb_fbops = { .fb_imageblit = cfb_imageblit, .fb_read = epson1355fb_read, .fb_write = epson1355fb_write, - .fb_cursor = soft_cursor, }; /* ------------------------------------------------------------------------- */ diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 10cd05059fe9..04417dc16c2e 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -57,9 +57,6 @@ static struct fb_ops ffb_ops = { .fb_sync = ffb_sync, .fb_mmap = ffb_mmap, .fb_ioctl = ffb_ioctl, - - /* XXX Use FFB hw cursor once fb cursor API is better understood... */ - .fb_cursor = soft_cursor, }; /* Register layout and definitions */ diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index a0763283d776..998374cfae6d 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -172,7 +172,6 @@ static struct fb_ops fm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index ed853bef19e9..9d5e4f342110 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1038,7 +1038,6 @@ static struct fb_ops gbefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 5a9b89c3831b..42fb9a89a792 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -14,7 +14,6 @@ config FB_GEODE_GX1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Framebuffer driver for the display controller integrated into the AMD Geode GX1 processor. diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 74a5fca86b8a..8e8da7433994 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -275,7 +275,6 @@ static struct fb_ops gx1fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 0d376ba54814..f04ca721f94c 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -262,7 +262,6 @@ static struct fb_ops hitfb_ops = { .fb_fillrect = hitfb_fillrect, .fb_copyarea = hitfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init hitfb_init(void) diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index e97fe8481d59..bebdac59d231 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -193,7 +193,6 @@ static struct fb_ops hpfb_ops = { .fb_fillrect = hpfb_fillrect, .fb_copyarea = hpfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = hpfb_sync, }; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7b9bf45ab6fe..7fbe24206b19 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1344,7 +1344,6 @@ static struct fb_ops imsttfb_ops = { .fb_fillrect = imsttfb_fillrect, .fb_copyarea = imsttfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = imsttfb_ioctl, }; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 64d9bcc38da3..e20b9f3a255f 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -298,7 +298,6 @@ static struct fb_ops imxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = imxfb_blank, - .fb_cursor = soft_cursor, /* FIXME: i.MX can do hardware cursor */ }; /* diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index e6d75b926dc8..0799b999b314 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1485,7 +1485,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #endif if (!dinfo->hwcursor) - return soft_cursor(info, cursor); + return -ENODEV; intelfbhw_cursor_hide(dinfo); diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index d8bac9e97842..5eb4d5c177bd 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -669,7 +669,6 @@ static struct fb_ops kyrofb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __devinit kyrofb_probe(struct pci_dev *pdev, diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 7e1e7fb168bd..84a7fe435bb8 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -51,7 +51,6 @@ static struct fb_ops leo_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = leo_mmap, .fb_ioctl = leo_ioctl, - .fb_cursor = soft_cursor, }; #define LEO_OFF_LC_SS0_KRN 0x00200000UL diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 4945a4c02209..cfc748e94272 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -589,7 +589,6 @@ static struct fb_ops macfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; void __init macfb_setup(char *options) diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index c7f3e1321224..a5c825d99466 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -122,7 +122,7 @@ void matrox_cfbX_init(WPMINFO2) { ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; - ACCESS_FBINFO(fbops).fb_cursor = soft_cursor; + ACCESS_FBINFO(fbops).fb_cursor = NULL; accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 429047ac615a..d52d7d825c41 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -576,7 +576,6 @@ static struct fb_ops matroxfb_dh_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_var_screeninfo matroxfb_dh_defined = { diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c index f192d995d030..743e7ad26acc 100644 --- a/drivers/video/maxinefb.c +++ b/drivers/video/maxinefb.c @@ -113,7 +113,6 @@ static struct fb_ops maxinefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init maxinefb_init(void) diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 5d424a30270a..8486e77872dc 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1665,7 +1665,6 @@ static struct fb_ops neofb_ops = { .fb_fillrect = neofb_fillrect, .fb_copyarea = neofb_copyarea, .fb_imageblit = neofb_imageblit, - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 691151e2bce3..cbe165bb181d 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1433,7 +1433,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->pixmap.flags = FB_PIXMAP_SYSTEM; if (!hwcur) - info->fbops->fb_cursor = soft_cursor; + info->fbops->fb_cursor = NULL; info->var.accel_flags = (!noaccel); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 611922c0b22f..2c856838694e 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -85,7 +85,6 @@ static struct fb_ops offb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index b76a5a9a125b..9aaf65fb623a 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -48,7 +48,6 @@ static struct fb_ops p9100_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = p9100_mmap, .fb_ioctl = p9100_ioctl, - .fb_cursor = soft_cursor, }; /* P9100 control registers */ diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index b00887e9851c..ca4082ae5a18 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -109,7 +109,6 @@ static struct fb_ops platinumfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 42c17efa9fb0..f4188fe6dd9a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1034,7 +1034,6 @@ static struct fb_ops pm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index c98f1c8d7dc2..f3927b6cda9d 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -128,7 +128,6 @@ static struct fb_ops pmagbafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index a483b13e117b..25148de5fe67 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -132,7 +132,6 @@ static struct fb_ops pmagbbfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 31c547fd383b..ec4bacf9dd2e 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -230,7 +230,6 @@ static struct fb_ops pvr2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_videomode pvr2_modedb[] __initdata = { diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index efd9333b05c2..f305a5b77b23 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -418,7 +418,6 @@ static struct fb_ops pxafb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = pxafb_blank, - .fb_cursor = soft_cursor, .fb_mmap = pxafb_mmap, }; diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 8416b2e2b501..bfc41f2c902a 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -84,7 +84,6 @@ static struct fb_ops q40fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init q40fb_probe(struct device *device) diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index a78b9bd8f897..600318f708f2 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -2218,7 +2218,6 @@ static struct fb_ops radeonfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index f4437430dc5f..3edbd14c5c46 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -388,7 +388,6 @@ static struct fb_ops s1d13xxxfb_fbops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor }; static int s1d13xxxfb_width_tab[2][4] __devinitdata = { diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 3cef90456a4b..bf679312be06 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -495,7 +495,6 @@ static struct fb_ops s3c2410fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 3d35b28aaac7..a5184575cfae 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -853,7 +853,6 @@ static struct fb_ops sa1100fb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = sa1100fb_blank, - .fb_cursor = soft_cursor, .fb_mmap = sa1100fb_mmap, }; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 7c285455c924..378ea1e34de7 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1470,7 +1470,6 @@ static struct fb_ops savagefb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 5ce81f44c769..2e8769dd345a 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -126,7 +126,6 @@ static struct fb_ops sgivwfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = sgivwfb_mmap, }; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 42c54b69726e..dea1a46c67c4 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -2002,7 +2002,9 @@ static struct fb_ops sisfb_ops = { .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, +#ifdef CONFIG_FB_SOFT_CURSOR .fb_cursor = soft_cursor, +#endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_compat_ioctl, diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 7b43716ab665..a01e7ecc15ed 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -457,11 +457,8 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) } /** - * xxxfb_cursor - REQUIRED function. If your hardware lacks support - * for a cursor you can use the default cursor whose - * function is called soft_cursor. It will always - * work since it uses xxxfb_imageblit function which - * is required. + * xxxfb_cursor - OPTIONAL. If your hardware lacks support + * for a cursor, leave this field NULL. * * @info: frame buffer structure that represents a single frame buffer * @cursor: structure defining the cursor to draw. @@ -663,7 +660,7 @@ static struct fb_ops xxxfb_ops = { .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ - .fb_cursor = xxxfb_cursor, /* Needed !!! */ + .fb_cursor = xxxfb_cursor, /* Optional !!! */ .fb_rotate = xxxfb_rotate, .fb_poll = xxxfb_poll, .fb_sync = xxxfb_sync, diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c deleted file mode 100644 index 229c4bc35079..000000000000 --- a/drivers/video/softcursor.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices - * - * Created 14 Nov 2002 by James Simmons - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include - -#include -#include - -int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - unsigned int scan_align = info->pixmap.scan_align - 1; - unsigned int buf_align = info->pixmap.buf_align - 1; - unsigned int i, size, dsize, s_pitch, d_pitch; - struct fb_image *image; - u8 *dst, *src; - - if (info->state != FBINFO_STATE_RUNNING) - return 0; - - s_pitch = (cursor->image.width + 7) >> 3; - dsize = s_pitch * cursor->image.height; - - src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); - if (!src) - return -ENOMEM; - - image = (struct fb_image *) (src + dsize); - *image = cursor->image; - d_pitch = (s_pitch + scan_align) & ~scan_align; - - size = d_pitch * image->height + buf_align; - size &= ~buf_align; - dst = fb_get_buffer_offset(info, &info->pixmap, size); - - if (cursor->enable) { - switch (cursor->rop) { - case ROP_XOR: - for (i = 0; i < dsize; i++) - src[i] = image->data[i] ^ cursor->mask[i]; - break; - case ROP_COPY: - default: - for (i = 0; i < dsize; i++) - src[i] = image->data[i] & cursor->mask[i]; - break; - } - } else - memcpy(src, image->data, dsize); - - fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); - image->data = dst; - info->fbops->fb_imageblit(info, image); - kfree(src); - return 0; -} - -EXPORT_SYMBOL(soft_cursor); - -MODULE_AUTHOR("James Simmons "); -MODULE_DESCRIPTION("Generic software cursor"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 663d53657fa4..e0f14df840d9 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1382,7 +1382,6 @@ static struct fb_ops sstfb_ops = { .fb_fillrect = cfb_fillrect, /* sstfb_fillrect */ .fb_copyarea = cfb_copyarea, /* sstfb_copyarea */ .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = sstfb_ioctl, }; diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 9e52794768e6..fbb17332afd7 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1147,7 +1147,6 @@ static struct fb_ops stifb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 1986a8b3833c..59fff29bc02e 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -52,7 +52,6 @@ static struct fb_ops tcx_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = tcx_mmap, .fb_ioctl = tcx_ioctl, - .fb_cursor = soft_cursor, }; /* THC definitions */ diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 7044226c5d4c..9d53387e6a66 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -184,7 +184,6 @@ static struct fb_ops tdfxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 9d9d2009ad8c..7398bd48ba6c 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -63,7 +63,6 @@ static struct fb_ops tgafb_ops = { .fb_fillrect = tgafb_fillrect, .fb_copyarea = tgafb_copyarea, .fb_imageblit = tgafb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 81a6d9f188cf..9ac2d3171187 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1293,7 +1293,6 @@ static struct fb_ops tridentfb_ops = { .fb_fillrect = tridentfb_fillrect, .fb_copyarea= tridentfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; module_init(tridentfb_init); diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c index 39d9ca71856b..d904da44e1aa 100644 --- a/drivers/video/tx3912fb.c +++ b/drivers/video/tx3912fb.c @@ -89,7 +89,6 @@ static struct fb_ops tx3912fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 31a2bbc53974..ce97ec8eae97 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -135,7 +135,6 @@ static struct fb_ops valkyriefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Sets the video mode according to info->var */ diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 3cc23106641d..4f02615225ac 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -215,7 +215,6 @@ static struct fb_ops vesafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init vesafb_setup(char *options) diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 92d46555dd86..8794dc5d2466 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -92,7 +92,6 @@ static struct fb_ops vfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = vfb_mmap, }; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index b46454c55c91..690bb6fe8281 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1326,7 +1326,6 @@ static struct fb_ops vga16fb_ops = { .fb_fillrect = vga16fb_fillrect, .fb_copyarea = vga16fb_copyarea, .fb_imageblit = vga16fb_imageblit, - .fb_cursor = soft_cursor, }; #ifndef MODULE diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index cf8cdb108fd9..48e70f153c4b 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -397,7 +397,6 @@ static struct fb_ops w100fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PM diff --git a/include/linux/fb.h b/include/linux/fb.h index c698055266d0..008ea71f4d7f 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -810,7 +810,6 @@ struct fb_info { extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_blank(struct fb_info *info, int blank); -extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); -- cgit v1.2.3 From 8fb6567e347a04d44b57e2b223cc5845859dfc6a Mon Sep 17 00:00:00 2001 From: Michal Januszewski Date: Mon, 7 Nov 2005 01:00:47 -0800 Subject: [PATCH] fbdev: fix the fb_find_nearest_mode() function Currently the fb_find_nearest_mode() function finds a mode with screen resolution closest to that described by the 'var' argument and with some arbitrary refresh rate (eg. in the following sequence of refresh rates: 70 60 53 85 75, 53 is selected). This patch fixes the function so that it looks for the closest mode as far as both resolution and refresh rate are concerned. The function's first argument is changed to fb_videomode so that the refresh rate can be specified by the caller, as fb_var_screeninfo doesn't have any fields that could directly hold this data. Signed-off-by: Michal Januszewski Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 3 ++- drivers/video/modedb.c | 24 +++++++++++++----------- include/linux/fb.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 5ff51cd0a2a9..3cf1b61ff1f8 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2715,7 +2715,8 @@ static void fbcon_new_modelist(struct fb_info *info) continue; vc = vc_cons[i].d; display_to_var(&var, &fb_display[i]); - mode = fb_find_nearest_mode(&var, &info->modelist); + mode = fb_find_nearest_mode(fb_display[i].mode, + &info->modelist); fb_videomode_to_var(&var, mode); if (vc) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 47516c44a390..aadef046ce7b 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -676,6 +676,8 @@ void fb_var_to_videomode(struct fb_videomode *mode, mode->sync = var->sync; mode->vmode = var->vmode & FB_VMODE_MASK; mode->flag = FB_MODE_IS_FROM_VAR; + mode->refresh = 0; + if (!var->pixclock) return; @@ -785,39 +787,39 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, } /** - * fb_find_nearest_mode - find mode closest video mode + * fb_find_nearest_mode - find closest videomode * - * @var: pointer to struct fb_var_screeninfo + * @mode: pointer to struct fb_videomode * @head: pointer to modelist * * Finds best matching videomode, smaller or greater in dimension. * If more than 1 videomode is found, will return the videomode with - * the closest refresh rate + * the closest refresh rate. */ -struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head) { struct list_head *pos; struct fb_modelist *modelist; - struct fb_videomode *mode, *best = NULL; + struct fb_videomode *cmode, *best = NULL; u32 diff = -1, diff_refresh = -1; list_for_each(pos, head) { u32 d; modelist = list_entry(pos, struct fb_modelist, list); - mode = &modelist->mode; + cmode = &modelist->mode; - d = abs(mode->xres - var->xres) + - abs(mode->yres - var->yres); + d = abs(cmode->xres - mode->xres) + + abs(cmode->yres - mode->yres); if (diff > d) { diff = d; - best = mode; + best = cmode; } else if (diff == d) { - d = abs(mode->refresh - best->refresh); + d = abs(cmode->refresh - mode->refresh); if (diff_refresh > d) { diff_refresh = d; - best = mode; + best = cmode; } } } diff --git a/include/linux/fb.h b/include/linux/fb.h index 008ea71f4d7f..68a787914d85 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -897,7 +897,7 @@ extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var, struct list_head *head); extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, struct list_head *head); -extern struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head); extern void fb_destroy_modelist(struct list_head *head); extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, -- cgit v1.2.3 From e07dea98761270249f33e733ff86420bc52ccab6 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:51 -0800 Subject: [PATCH] console: Fix compile error Fix following compile error (From Kernel Bugzilla Bug 5427): include/linux/console_struct.h:53: error: field `vt_mode' has incomplete type Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/console_struct.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 725be90ef55e..f8e5587a0f92 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -9,6 +9,8 @@ * to achieve effects such as fast scrolling by changing the origin. */ +#include + struct vt_struct; #define NPAR 16 -- cgit v1.2.3 From 998e6d51162707685336ff99c029c8911b270d32 Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Mon, 7 Nov 2005 01:00:52 -0800 Subject: [PATCH] fbcon: Add rl (Roman Large) font I converted the "rl" console font from the kbd utility to be a built-in font for the framebuffer console, and I was wondering if you would be OK with including it. I've generated a font_rl.c file and related minor modifications. I find it's the most visually appealing of the kbd fonts which is why I use it and selected it for conversion. I believe the font is GPL'd. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 7 + drivers/video/console/Makefile | 1 + drivers/video/console/font_rl.c | 4374 +++++++++++++++++++++++++++++++++++++++ drivers/video/console/fonts.c | 4 + include/linux/font.h | 2 + 5 files changed, 4388 insertions(+) create mode 100644 drivers/video/console/font_rl.c (limited to 'include') diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 81d44995f9eb..fadf7c5d216e 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -205,5 +205,12 @@ config FONT_10x18 big letters. It fits between the sun 12x22 and the normal 8x16 font. If other fonts are too big or too small for you, say Y, otherwise say N. +config FONT_RL + bool "console Roman Large 8x16 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + help + This is the visually-appealing "RL" console font that is + included with the kbd package. + endmenu diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 71b4b626e328..5222628accce 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -15,6 +15,7 @@ font-objs-$(CONFIG_FONT_10x18) += font_10x18.o font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o +font-objs-$(CONFIG_FONT_RL) += font_rl.o font-objs += $(font-objs-y) diff --git a/drivers/video/console/font_rl.c b/drivers/video/console/font_rl.c new file mode 100644 index 000000000000..dfecc27d8ded --- /dev/null +++ b/drivers/video/console/font_rl.c @@ -0,0 +1,4374 @@ + +/* This font is simply the "rl.fnt" console font from the kbd utility. + * Converted by Zack T Smith, fbui@comcast.net. + * The original binary file is covered under the GNU Public License. + */ + +#include + +#define FONTDATAMAX 4096 + +static unsigned char patterns[4096] = { +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x42, +0x81, +0xe7, +0xa5, +0x99, +0x81, +0x81, +0x99, +0x42, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x7e, +0xff, +0x99, +0xdb, +0xe7, +0xff, +0xff, +0xe7, +0x7e, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x6c, +0xfe, +0xfe, +0xfe, +0xfe, +0xfe, +0x7c, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x7c, +0xfe, +0x7c, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x38, +0x38, +0x10, +0xd6, +0xfe, +0xd6, +0x10, +0x10, +0x38, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xfe, +0xfe, +0x54, +0x10, +0x10, +0x38, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x3c, +0x3c, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xe7, +0xc3, +0xc3, +0xe7, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x42, +0x42, +0x66, +0x3c, +0x00, +0x00, +0x00, +0x00, +0x00, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xc3, +0x99, +0xbd, +0xbd, +0x99, +0xc3, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x0f, +0x07, +0x0d, +0x18, +0x78, +0xcc, +0xcc, +0xcc, +0xcc, +0x78, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x3c, +0x18, +0x7e, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x0c, +0x0a, +0x0a, +0x0a, +0x08, +0x08, +0x08, +0x38, +0x78, +0x30, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x18, +0x1c, +0x1e, +0x1e, +0x16, +0x12, +0x72, +0xf2, +0x62, +0x0e, +0x1e, +0x0c, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x92, +0x54, +0x38, +0xfe, +0x38, +0x54, +0x92, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x80, +0xc0, +0xe0, +0xb8, +0x8e, +0xb8, +0xe0, +0xc0, +0x80, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x06, +0x0e, +0x3a, +0xe2, +0x3a, +0x0e, +0x06, +0x02, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0x00, +0x00, + +0x00, +0x42, +0xe7, +0xe7, +0xe7, +0xe7, +0x42, +0x42, +0x42, +0x00, +0x66, +0x66, +0x66, +0x00, +0x00, +0x00, + +0x00, +0x7f, +0xca, +0xca, +0xca, +0xca, +0x7a, +0x0a, +0x0a, +0x0a, +0x0a, +0x0a, +0x1b, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x78, +0xcc, +0xc6, +0xc3, +0x63, +0x33, +0x1e, +0x8c, +0x78, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0xfe, +0xfe, +0xfe, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0xfe, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x08, +0x0c, +0x06, +0xff, +0x06, +0x0c, +0x08, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x30, +0x60, +0xff, +0x60, +0x30, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x22, +0x44, +0x88, +0xcc, +0xee, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x24, +0x42, +0xff, +0x42, +0x24, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x38, +0x38, +0x6c, +0x6c, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0xfe, +0xc6, +0x6c, +0x6c, +0x38, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x3c, +0x3c, +0x3c, +0x3c, +0x18, +0x18, +0x18, +0x10, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x22, +0x77, +0x33, +0x11, +0x22, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x12, +0x12, +0x12, +0x7f, +0x24, +0x24, +0x24, +0xfe, +0x48, +0x48, +0x48, +0x00, +0x00, +0x00, + +0x10, +0x10, +0x7c, +0xd2, +0xd0, +0xd0, +0xd0, +0x7c, +0x16, +0x16, +0x16, +0x96, +0x7c, +0x10, +0x10, +0x00, + +0x00, +0x42, +0xbe, +0x44, +0x0c, +0x08, +0x18, +0x10, +0x30, +0x20, +0x64, +0x4a, +0xc4, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x6c, +0x6c, +0x6c, +0x38, +0x37, +0x72, +0xdc, +0xcc, +0xcc, +0xcc, +0x77, +0x00, +0x00, +0x00, + +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x04, +0x08, +0x10, +0x10, +0x30, +0x30, +0x30, +0x30, +0x30, +0x10, +0x10, +0x08, +0x04, +0x00, +0x00, + +0x00, +0x20, +0x10, +0x08, +0x08, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x08, +0x08, +0x10, +0x20, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x44, +0x28, +0x38, +0xfe, +0x38, +0x28, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x7e, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x06, +0x06, +0x0c, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x60, +0x60, +0xc0, +0xc0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x3c, +0x46, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc4, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x08, +0x18, +0x78, +0x18, +0x18, +0x18, +0x18, +0x18, +0x7e, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x7c, +0x86, +0x06, +0x0c, +0x18, +0x20, +0x40, +0xc1, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x3c, +0x46, +0x04, +0x08, +0x1c, +0x06, +0x06, +0x06, +0x06, +0x0c, +0x70, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x04, +0x08, +0x10, +0x2c, +0x4c, +0x8c, +0x8c, +0xfe, +0x0c, +0x0c, +0x0c, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x3c, +0x20, +0x20, +0x70, +0x0c, +0x06, +0x06, +0x06, +0x06, +0x0c, +0x70, +0x00, + +0x00, +0x00, +0x18, +0x20, +0x40, +0xc0, +0xdc, +0xc6, +0xc6, +0xc6, +0xc6, +0x44, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x40, +0x7e, +0x82, +0x06, +0x04, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x30, +0x30, +0x00, + +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0x64, +0x38, +0x4c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x38, +0x44, +0xc6, +0xc6, +0x76, +0x06, +0x06, +0x06, +0x04, +0x08, +0x30, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, + +0x00, +0x06, +0x0c, +0x18, +0x30, +0x60, +0xa0, +0xa0, +0x60, +0x30, +0x18, +0x0c, +0x06, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x60, +0x30, +0x18, +0x0c, +0x06, +0x05, +0x05, +0x06, +0x0c, +0x18, +0x30, +0x60, +0x00, +0x00, +0x00, + +0x00, +0x7c, +0x86, +0xc6, +0x06, +0x04, +0x08, +0x10, +0x10, +0x18, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x46, +0xc6, +0xce, +0xd6, +0xd6, +0xd6, +0xdc, +0xc0, +0xc4, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x66, +0x66, +0x66, +0x66, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x61, +0x60, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x61, +0x61, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xcf, +0xc6, +0xc6, +0xc6, +0x66, +0x38, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x7e, +0x62, +0x62, +0x62, +0x62, +0x62, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x08, +0xf0, + +0x00, +0xf7, +0x64, +0x6c, +0x68, +0x68, +0x78, +0x6c, +0x6c, +0x6c, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0xf8, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0xc3, +0x66, +0x76, +0x7e, +0x56, +0x56, +0x46, +0x46, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xe7, +0x62, +0x62, +0x72, +0x52, +0x5a, +0x4a, +0x4e, +0x46, +0x46, +0x42, +0xe2, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x6c, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x10, +0x39, +0x0e, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x6c, +0x66, +0x66, +0x66, +0x66, +0xf3, +0x00, +0x00, +0x00, + +0x00, +0x7a, +0xc6, +0xc2, +0xc0, +0x70, +0x3c, +0x0e, +0x06, +0x06, +0x86, +0xc6, +0xbc, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x99, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x76, +0x34, +0x34, +0x34, +0x3c, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x6a, +0x6a, +0x6a, +0x6a, +0x7e, +0x7e, +0x34, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x2c, +0x2c, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x7f, +0x46, +0x86, +0x0c, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x61, +0x62, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xc0, +0xc0, +0x60, +0x60, +0x30, +0x30, +0x18, +0x18, +0x0c, +0x0c, +0x06, +0x06, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x38, +0x4c, +0x86, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, + +0x00, +0x18, +0x20, +0x30, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x6c, +0x76, +0x66, +0x66, +0x66, +0x66, +0x76, +0x6c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x60, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x04, +0x1c, +0x0c, +0x0c, +0x6c, +0xdc, +0xcc, +0xcc, +0xcc, +0xcc, +0xdc, +0x66, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x33, +0x30, +0x30, +0x78, +0x30, +0x30, +0x30, +0x30, +0x30, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7b, +0xce, +0xcc, +0xcc, +0xcc, +0x78, +0x60, +0x7c, +0x86, +0xc6, +0x7c, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x6c, +0x76, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x38, +0x10, +0x00, +0x18, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x1c, +0x08, +0x00, +0x0c, +0x1c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x6c, +0x4c, +0x38, +0x00, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x67, +0x66, +0x6c, +0x78, +0x6c, +0x6c, +0x66, +0xe7, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x6a, +0xfe, +0x6a, +0x6a, +0x6a, +0x62, +0x62, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5c, +0xf6, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5c, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x60, +0x60, +0xf0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xcc, +0xcc, +0xcc, +0xcc, +0xcc, +0xcc, +0x7c, +0x0c, +0x0c, +0x1e, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5e, +0xf6, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7a, +0xc6, +0x72, +0x1c, +0x06, +0x86, +0xc6, +0xbc, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x30, +0x7c, +0x30, +0x30, +0x30, +0x30, +0x30, +0x34, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x76, +0x34, +0x34, +0x3c, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x6a, +0x6a, +0x6a, +0x6a, +0x7e, +0x24, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x34, +0x18, +0x2c, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x10, +0xb0, +0xe0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x8c, +0x18, +0x30, +0x30, +0x60, +0xc2, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x0e, +0x18, +0x10, +0x10, +0x08, +0x70, +0x70, +0x08, +0x10, +0x10, +0x18, +0x0e, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x00, +0x00, + +0x00, +0x70, +0x18, +0x08, +0x08, +0x10, +0x0e, +0x0e, +0x10, +0x08, +0x08, +0x18, +0x70, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x6c, +0xc6, +0xc6, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0x62, +0x3c, +0x18, +0x0c, +0x24, +0x18, + +0x00, +0x00, +0x66, +0x00, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3b, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x58, +0x8c, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x38, +0x44, +0x44, +0x38, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x60, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x08, +0x24, +0x18, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x60, +0x30, +0x08, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x66, +0x18, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x18, +0x24, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x0c, +0x18, +0xff, +0x61, +0x60, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0x9b, +0x1b, +0x3f, +0xd8, +0xd8, +0xd9, +0x6e, +0x00, +0x00, +0x00, + +0x00, +0x1f, +0x1d, +0x1d, +0x3c, +0x2c, +0x2e, +0x2c, +0x7c, +0x4c, +0x4c, +0x4d, +0xef, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x10, +0xb0, +0xe0, + +0x66, +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x66, +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x10, +0x10, +0x7c, +0xc6, +0xc0, +0xc0, +0xc0, +0xc0, +0xc2, +0x7c, +0x10, +0x10, +0x00, + +0x00, +0x38, +0x64, +0x6c, +0x60, +0x60, +0xf0, +0x60, +0x60, +0x60, +0x60, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0x81, +0xc3, +0x66, +0x3c, +0x18, +0xff, +0x18, +0x18, +0xff, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0xfe, +0x63, +0x63, +0x63, +0x63, +0x6e, +0x60, +0x64, +0x6e, +0x64, +0x64, +0xf5, +0x06, +0x00, +0x00, + +0x00, +0x0e, +0x19, +0x1b, +0x18, +0x18, +0x3c, +0x18, +0x18, +0x18, +0x18, +0xd8, +0x98, +0x70, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x06, +0x0c, +0x10, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x32, +0x4c, +0x00, +0x5c, +0xf6, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x32, +0x4c, +0x00, +0xe7, +0x72, +0x52, +0x5a, +0x4a, +0x4e, +0x46, +0x46, +0x42, +0xe2, +0x00, +0x00, +0x00, + +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x30, +0x00, +0x30, +0x10, +0x10, +0x20, +0x40, +0xc0, +0xc6, +0xc2, +0x7c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0xc0, +0xc0, +0xc0, +0xc0, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x06, +0x06, +0x06, +0x06, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x63, +0x66, +0xfc, +0x18, +0x30, +0x60, +0xce, +0x93, +0x06, +0x0c, +0x1f, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x63, +0x66, +0xfc, +0x18, +0x30, +0x64, +0xc8, +0x96, +0x3f, +0x06, +0x06, +0x00, +0x00, + +0x00, +0x18, +0x18, +0x00, +0x08, +0x18, +0x18, +0x18, +0x3c, +0x3c, +0x3c, +0x3c, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x36, +0x6c, +0xd8, +0xd8, +0x6c, +0x36, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xd8, +0x6c, +0x36, +0x36, +0x6c, +0xd8, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, + +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, + +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xf8, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x06, +0x06, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x06, +0x06, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x06, +0x06, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x60, +0x60, +0x7f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0x60, +0x60, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe7, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xe7, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x60, +0x60, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe7, +0x00, +0x00, +0xe7, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x1f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x1f, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xff, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, + +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x77, +0xcc, +0xcc, +0xcc, +0xcc, +0xde, +0x73, +0x00, +0x00, +0x00, + +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc4, +0xc8, +0xc4, +0xc6, +0xc6, +0xc6, +0xc6, +0xdc, +0xc0, +0xc0, +0x00, + +0x00, +0xff, +0x61, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x01, +0x7e, +0xa4, +0x24, +0x2c, +0x6c, +0x6c, +0x6c, +0x48, +0x00, +0x00, +0x00, + +0x00, +0xff, +0xc1, +0x60, +0x30, +0x18, +0x0c, +0x18, +0x30, +0x60, +0xc0, +0xc1, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0xc8, +0xc8, +0xc8, +0xc8, +0xc8, +0xc8, +0x70, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x22, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x60, +0x60, +0x60, +0xc0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x18, +0x18, +0x18, +0x18, +0x18, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x10, +0x7c, +0xd6, +0xd6, +0xd6, +0xd6, +0xd6, +0xd6, +0x7c, +0x10, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x6c, +0xc6, +0xc6, +0xc6, +0xfe, +0xc6, +0xc6, +0xc6, +0xc6, +0x6c, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x24, +0x24, +0xa5, +0xe7, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x30, +0x18, +0x0c, +0x3e, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x6e, +0xff, +0x99, +0x99, +0x99, +0x99, +0xff, +0x76, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x04, +0x7c, +0xca, +0x92, +0xa6, +0x7c, +0x40, +0x80, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x1c, +0x30, +0x60, +0x60, +0x60, +0x7c, +0x60, +0x60, +0x60, +0x60, +0x30, +0x1c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x7c, +0x00, +0x00, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x7e, +0x18, +0x18, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x30, +0x18, +0x0c, +0x06, +0x0c, +0x18, +0x30, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x0c, +0x18, +0x30, +0x60, +0x30, +0x18, +0x0c, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x0e, +0x19, +0x1b, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xd8, +0x98, +0x70, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x00, +0x7e, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x44, +0x44, +0x44, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x07, +0x06, +0x06, +0x0c, +0x0c, +0x08, +0x98, +0xd0, +0xf0, +0x60, +0x20, +0x00, +0x00, +0x00, + +0x00, +0xcc, +0x76, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x70, +0x98, +0x18, +0x30, +0x60, +0x88, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7c, +0x64, +0x64, +0x64, +0x64, +0x64, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +}; + + +const struct font_desc font_rl = { + RL_IDX, + "RomanLarge", + 8, + 16, + patterns, + -1 +}; diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 4fd07d9eca03..9be83bed1959 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -64,6 +64,10 @@ static const struct font_desc *fonts[] = { #undef NO_FONTS &font_mini_4x6, #endif +#ifdef CONFIG_FONT_RL +#undef NO_FONTS + &font_rl, +#endif }; #define num_fonts (sizeof(fonts)/sizeof(*fonts)) diff --git a/include/linux/font.h b/include/linux/font.h index 53b129f07f6f..8aac48c37f3d 100644 --- a/include/linux/font.h +++ b/include/linux/font.h @@ -31,6 +31,7 @@ struct font_desc { #define SUN12x22_IDX 7 #define ACORN8x8_IDX 8 #define MINI4x6_IDX 9 +#define RL_IDX 10 extern const struct font_desc font_vga_8x8, font_vga_8x16, @@ -41,6 +42,7 @@ extern const struct font_desc font_vga_8x8, font_sun_8x16, font_sun_12x22, font_acorn_8x8, + font_rl, font_mini_4x6; /* Find a font with a specific name */ -- cgit v1.2.3 From 003cfc0c56977f1c3ce48ddfd2073b7c6d75a5d8 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:54 -0800 Subject: [PATCH] fbdev: Add helper to get an appropriate initial mode Add new helper, fb_find_best_display(), which will search the modelist for the best mode for the attached display. This requires an EDID block that is converted to struct fb_monspecs and a private modelist. The search will be done in this manner: - if 1st detailed timing is preferred, use that - else if dimensions of the display are known, use that to estimate xres and - else if modelist has detailed timings, use the first detailed timing - else, use the very first entry from the modelist Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/modedb.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 2 ++ 2 files changed, 62 insertions(+) (limited to 'include') diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index aadef046ce7b..1789a52d776a 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -944,6 +944,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, } } +struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head) +{ + struct list_head *pos; + struct fb_modelist *modelist; + struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL; + int first = 0; + + if (!head->prev || !head->next || list_empty(head)) + goto finished; + + /* get the first detailed mode and the very first mode */ + list_for_each(pos, head) { + modelist = list_entry(pos, struct fb_modelist, list); + m = &modelist->mode; + + if (!first) { + m1 = m; + first = 1; + } + + if (m->flag & FB_MODE_IS_FIRST) { + md = m; + break; + } + } + + /* first detailed timing is preferred */ + if (specs->misc & FB_MISC_1ST_DETAIL) { + best = md; + goto finished; + } + + /* find best mode based on display width and height */ + if (specs->max_x && specs->max_y) { + struct fb_var_screeninfo var; + + memset(&var, 0, sizeof(struct fb_var_screeninfo)); + var.xres = (specs->max_x * 7200)/254; + var.yres = (specs->max_y * 7200)/254; + m = fb_find_best_mode(&var, head); + if (m) { + best = m; + goto finished; + } + } + + /* use first detailed mode */ + if (md) { + best = md; + goto finished; + } + + /* last resort, use the very first mode */ + best = m1; +finished: + return best; +} +EXPORT_SYMBOL(fb_find_best_display); + EXPORT_SYMBOL(fb_videomode_to_var); EXPORT_SYMBOL(fb_var_to_videomode); EXPORT_SYMBOL(fb_mode_is_equal); diff --git a/include/linux/fb.h b/include/linux/fb.h index 68a787914d85..e7ff98e395f6 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -902,6 +902,8 @@ extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, extern void fb_destroy_modelist(struct list_head *head); extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, struct list_head *head); +extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head); /* drivers/video/fbcmap.c */ extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); -- cgit v1.2.3 From 63921fbfbd87ec745e65d2e9aecdfdc9a4ce73f2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 7 Nov 2005 01:00:57 -0800 Subject: [PATCH] matroxfb: Add support for Mystique AGP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new entries for Mystique AGP with the PCI ID 0x051e. I don't actually have such boards but according to google they do exist. Curiosly X.Org doesn't recognize that PCI ID. And what's even more interesting is that Matrox's own Windows drivers don't recognize it either. After going through about a dozen different versions I did find one older driver that does list this particular ID. It is also listed in the pci.ids file. I'm not sure if non-220 AGP chips exist. I left the chip revision check intact for AGP chips nonetheless. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_base.c | 14 ++++++++++++++ include/linux/pci_ids.h | 1 + 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 5f2df1725e6e..1734438f7d7c 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1428,6 +1428,20 @@ static struct board { MGA_1164, &vbMystique, "Mystique 220 (PCI)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02, + 0, 0, + DEVF_VIDEO64BIT | DEVF_CROSS4MB, + 180000, + MGA_1064, + &vbMystique, + "Mystique (AGP)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF, + 0, 0, + DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + 220000, + MGA_1164, + &vbMystique, + "Mystique 220 (AGP)"}, #endif #ifdef CONFIG_FB_MATROX_G {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 88de3f8ce1a2..cd62a39ce068 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -519,6 +519,7 @@ #define PCI_DEVICE_ID_MATROX_MIL 0x0519 #define PCI_DEVICE_ID_MATROX_MYS 0x051A #define PCI_DEVICE_ID_MATROX_MIL_2 0x051b +#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e #define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f #define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 #define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 -- cgit v1.2.3 From 6c8bec6d5f24b01c53b792b06a645e78d482020d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:04 -0800 Subject: [PATCH] jbd doc: fix some kernel-doc warnings Add structure fields kernel-doc for 2 fields in struct journal_s. Warning(/var/linsrc/linux-2614-rc4//include/linux/jbd.h:808): No description found for parameter 'j_wbuf' Warning(/var/linsrc/linux-2614-rc4//include/linux/jbd.h:808): No description found for parameter 'j_wbufsize' Convert fs/jbd/recovery.c non-static functions to kernel-doc format. fs/jbd/recovery.c doesn't export any symbols, so it should use !I instead of !E to eliminate this warning message: Warning(/var/linsrc/linux-2614-rc4//fs/jbd/recovery.c): no structured comments found Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/journal-api.tmpl | 2 +- fs/jbd/recovery.c | 4 ++-- include/linux/jbd.h | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl index 341aaa4ce481..2077f9a28c19 100644 --- a/Documentation/DocBook/journal-api.tmpl +++ b/Documentation/DocBook/journal-api.tmpl @@ -306,7 +306,7 @@ an example.
Journal Level !Efs/jbd/journal.c -!Efs/jbd/recovery.c +!Ifs/jbd/recovery.c Transasction Level !Efs/jbd/transaction.c diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 103c34e4fb28..80d7f53fd0a7 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -210,7 +210,7 @@ do { \ } while (0) /** - * int journal_recover(journal_t *journal) - recovers a on-disk journal + * journal_recover - recovers a on-disk journal * @journal: the journal to recover * * The primary function for recovering the log contents when mounting a @@ -266,7 +266,7 @@ int journal_recover(journal_t *journal) } /** - * int journal_skip_recovery() - Start journal and wipe exiting records + * journal_skip_recovery - Start journal and wipe exiting records * @journal: journal to startup * * Locate any valid recovery information from the journal and set up the diff --git a/include/linux/jbd.h b/include/linux/jbd.h index be197eb90077..aa56172c6fed 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -611,6 +611,9 @@ struct transaction_s * @j_revoke: The revoke table - maintains the list of revoked blocks in the * current transaction. * @j_revoke_table: alternate revoke tables for j_revoke + * @j_wbuf: array of buffer_heads for journal_commit_transaction + * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the + * number that will fit in j_blocksize * @j_private: An opaque pointer to fs-private information. */ -- cgit v1.2.3 From 8f2709b542c96a2b1910ca5f2fe27dc9023b1225 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:05 -0800 Subject: [PATCH] kernel-doc: fix some kernel-api warnings Fix various warnings in kernel-doc: Warning(linux-2614-rc4//include/linux/net.h:89): Enum value 'SOCK_DCCP' not described in enum 'sock_type' usercopy.c: should use !E instead of !I for exported symbols: Warning(linux-2614-rc4//arch/i386/lib/usercopy.c): no structured comments found fs.h does not need to use !E since it has no exported symbols: Warning(linux-2614-rc4//include/linux/fs.h:1182): No description found for parameter 'find_exported_dentry' Warning(linux-2614-rc4//include/linux/fs.h): no structured comments found irq/manage.c should use !E for its exported symbols: Warning(linux-2614-rc4//kernel/irq/manage.c): no structured comments found macmodes.c should use !E for its exported symbols: Warning(linux-2614-rc4//drivers/video/macmodes.c): no structured comments found Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-api.tmpl | 7 +++---- include/linux/fs.h | 2 ++ include/linux/net.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index ec474e5a25ed..a8316b1a3e3d 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -118,7 +118,7 @@ X!Ilib/string.c User Space Memory Access !Iinclude/asm-i386/uaccess.h -!Iarch/i386/lib/usercopy.c +!Earch/i386/lib/usercopy.c More Memory Management Functions !Iinclude/linux/rmap.h @@ -174,7 +174,6 @@ X!Ilib/string.c The Linux VFS The Filesystem types !Iinclude/linux/fs.h -!Einclude/linux/fs.h The Directory Cache !Efs/dcache.c @@ -266,7 +265,7 @@ X!Ekernel/module.c Hardware Interfaces Interrupt Handling -!Ikernel/irq/manage.c +!Ekernel/irq/manage.c Resources Management @@ -501,7 +500,7 @@ KAO --> !Edrivers/video/modedb.c Frame Buffer Macintosh Video Mode Database -!Idrivers/video/macmodes.c +!Edrivers/video/macmodes.c Frame Buffer Fonts diff --git a/include/linux/fs.h b/include/linux/fs.h index 0c89fc9481a8..9a593ef262ef 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1096,6 +1096,8 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc); * @get_name: find the name for a given inode in a given directory * @get_parent: find the parent of a given directory * @get_dentry: find a dentry for the inode given a file handle sub-fragment + * @find_exported_dentry: + * set by the exporting module to a standard helper function. * * Description: * The export_operations structure provides a means for nfsd to communicate diff --git a/include/linux/net.h b/include/linux/net.h index 4e981585a89a..d6a41e6577f6 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -71,6 +71,7 @@ typedef enum { * @SOCK_RAW: raw socket * @SOCK_RDM: reliably-delivered message * @SOCK_SEQPACKET: sequential packet socket + * @SOCK_DCCP: Datagram Congestion Control Protocol socket * @SOCK_PACKET: linux specific way of getting packets at the dev level. * For writing rarp and other similar things on the user level. * -- cgit v1.2.3 From b8887e6e8c04bcefb512cdb08fc7e9c310ac847e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:07 -0800 Subject: [PATCH] kernel-docs: fix kernel-doc format problems Convert to proper kernel-doc format. Some have extra blank lines (not allowed immed. after the function name) or need blank lines (after all parameters). Function summary must be only one line. Colon (":") in a function description does weird things (causes kernel-doc to think that it's a new section head sadly). Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/ll_rw_blk.c | 1 - fs/fs-writeback.c | 5 +++-- include/linux/kernel.h | 1 - kernel/sys.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 2747741677fb..5f52e30b43f8 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -706,7 +706,6 @@ EXPORT_SYMBOL(blk_queue_dma_alignment); /** * blk_queue_find_tag - find a request by its tag and queue - * * @q: The request queue for the device * @tag: The tag of the request * diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1361a4a64157..785c7213a54f 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -606,7 +606,7 @@ EXPORT_SYMBOL(sync_inode); * O_SYNC flag set, to flush dirty writes to disk. * * @what is a bitmask, specifying which part of the inode's data should be - * written and waited upon: + * written and waited upon. * * OSYNC_DATA: i_mapping's dirty data * OSYNC_METADATA: the buffers at i_mapping->private_list @@ -672,8 +672,9 @@ int writeback_acquire(struct backing_dev_info *bdi) /** * writeback_in_progress: determine whether there is writeback in progress - * against a backing device. * @bdi: the device's backing_dev_info structure. + * + * Determine whether there is writeback in progress against a backing device. */ int writeback_in_progress(struct backing_dev_info *bdi) { diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f1925ccc9fe1..b6419489b27b 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -266,7 +266,6 @@ extern void dump_stack(void); /** * container_of - cast a member of a structure out to the containing structure - * * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. diff --git a/kernel/sys.c b/kernel/sys.c index 3e332131000e..bce933ebb29f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -386,7 +386,7 @@ void kernel_restart_prepare(char *cmd) /** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart - * or NULL + * or %NULL * * Shutdown everything and perform a clean reboot. * This is not safe to call in interrupt context. -- cgit v1.2.3 From 24622efd11fc5ee569b008b9f89e5e268265811b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:44 -0800 Subject: [PATCH] __deprecated_for_modules: insert_resource This looks like something which out-of-tree code could possibly be using. Give insert_resource the twelve-month treatment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ include/linux/ioport.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b67189a8d8d4..7fd8c80fa0fc 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -69,6 +69,14 @@ Who: Grant Coady --------------------------- +What: remove EXPORT_SYMBOL(insert_resource) +When: April 2006 +Files: kernel/resource.c +Why: No modular usage in the kernel. +Who: Adrian Bunk + +--------------------------- + What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl]) When: November 2005 Files: drivers/pcmcia/: pcmcia_ioctl.c diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 18d010bee635..cd6bd001ba4e 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -94,7 +94,7 @@ extern struct resource iomem_resource; extern int request_resource(struct resource *root, struct resource *new); extern struct resource * ____request_resource(struct resource *root, struct resource *new); extern int release_resource(struct resource *new); -extern int insert_resource(struct resource *parent, struct resource *new); +extern __deprecated_for_modules int insert_resource(struct resource *parent, struct resource *new); extern int allocate_resource(struct resource *root, struct resource *new, unsigned long size, unsigned long min, unsigned long max, -- cgit v1.2.3 From dfed04492f2459e47dcb290be6ed5a8bc37096d5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:44 -0800 Subject: [PATCH] __deprecated_for_modules: panic_timeout This looks like something which out-of-tree code could possibly be using. Give panic_timeout the twelve-month treatment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ include/linux/kernel.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 7fd8c80fa0fc..decdf9917e0d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -69,6 +69,14 @@ Who: Grant Coady --------------------------- +What: remove EXPORT_SYMBOL(panic_timeout) +When: April 2006 +Files: kernel/panic.c +Why: No modular usage in the kernel. +Who: Adrian Bunk + +--------------------------- + What: remove EXPORT_SYMBOL(insert_resource) When: April 2006 Files: kernel/resource.c diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b6419489b27b..b1e407a4fbda 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -168,7 +168,7 @@ static inline void console_verbose(void) extern void bust_spinlocks(int yes); extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */ -extern int panic_timeout; +extern __deprecated_for_modules int panic_timeout; extern int panic_on_oops; extern int tainted; extern const char *print_tainted(void); -- cgit v1.2.3 From b449f63c8ce4a517cb91f237cc3d68d083ec2dd3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:48 -0800 Subject: [PATCH] drivers/pnp/: cleanups This patch contains the following possible cleanups: - make needlessly global code static - #if 0 the following unused global function: - core.c: pnp_remove_device - #if 0 the following unneeded EXPORT_SYMBOL's: - card.c: pnp_add_card - card.c: pnp_remove_card - card.c: pnp_add_card_device - card.c: pnp_remove_card_device - card.c: pnp_add_card_id - core.c: pnp_register_protocol - core.c: pnp_unregister_protocol - core.c: pnp_add_device - core.c: pnp_remove_device - pnpacpi/core.c: pnpacpi_protocol - driver.c: pnp_add_id - isapnp/core.c: isapnp_read_byte - manager.c: pnp_auto_config_dev - resource.c: pnp_register_dependent_option - resource.c: pnp_register_independent_option - resource.c: pnp_register_irq_resource - resource.c: pnp_register_dma_resource - resource.c: pnp_register_port_resource - resource.c: pnp_register_mem_resource Note that this patch #if 0's exactly one functions and removes no functions. Most it does is the #if 0 of EXPORT_SYMBOL's, so if any modular code will use any of them, re-adding will be trivial. Modular ISAPnP might be interesting in some cases, but this is more legacy code. If someone would work on it to sort all the issues out (starting with the point that most users of __ISAPNP__ will have to be fixed) re-enabling the required EXPORT_SYMBOL's won't be hard for him. Signed-off-by: Adrian Bunk Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/card.c | 4 +++- drivers/pnp/core.c | 5 ++++- drivers/pnp/driver.c | 2 ++ drivers/pnp/isapnp/core.c | 2 ++ drivers/pnp/manager.c | 2 ++ drivers/pnp/pnpacpi/core.c | 6 ++++-- drivers/pnp/resource.c | 2 ++ include/linux/pnp.h | 2 -- 8 files changed, 19 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index e95ed67d4f05..bd7c966ea2d7 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -12,7 +12,7 @@ #include "base.h" LIST_HEAD(pnp_cards); -LIST_HEAD(pnp_card_drivers); +static LIST_HEAD(pnp_card_drivers); static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) @@ -374,11 +374,13 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv) pnp_unregister_driver(&drv->link); } +#if 0 EXPORT_SYMBOL(pnp_add_card); EXPORT_SYMBOL(pnp_remove_card); EXPORT_SYMBOL(pnp_add_card_device); EXPORT_SYMBOL(pnp_remove_card_device); EXPORT_SYMBOL(pnp_add_card_id); +#endif /* 0 */ EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); EXPORT_SYMBOL(pnp_register_card_driver); diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index deed92459bc5..aec83ec5ea23 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -158,13 +158,14 @@ void __pnp_remove_device(struct pnp_dev *dev) * * this function will free all mem used by dev */ - +#if 0 void pnp_remove_device(struct pnp_dev *dev) { if (!dev || dev->card) return; __pnp_remove_device(dev); } +#endif /* 0 */ static int __init pnp_init(void) { @@ -174,7 +175,9 @@ static int __init pnp_init(void) subsys_initcall(pnp_init); +#if 0 EXPORT_SYMBOL(pnp_register_protocol); EXPORT_SYMBOL(pnp_unregister_protocol); EXPORT_SYMBOL(pnp_add_device); EXPORT_SYMBOL(pnp_remove_device); +#endif /* 0 */ diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 33da25f3213f..d3ccce706ab4 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -214,6 +214,8 @@ int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) EXPORT_SYMBOL(pnp_register_driver); EXPORT_SYMBOL(pnp_unregister_driver); +#if 0 EXPORT_SYMBOL(pnp_add_id); +#endif EXPORT_SYMBOL(pnp_device_attach); EXPORT_SYMBOL(pnp_device_detach); diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index beedd86800f4..57fd60314d59 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -941,7 +941,9 @@ EXPORT_SYMBOL(isapnp_protocol); EXPORT_SYMBOL(isapnp_present); EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); +#if 0 EXPORT_SYMBOL(isapnp_read_byte); +#endif EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index cbb2749db178..261668618b2d 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -555,7 +555,9 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne EXPORT_SYMBOL(pnp_manual_config_dev); +#if 0 EXPORT_SYMBOL(pnp_auto_config_dev); +#endif EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); EXPORT_SYMBOL(pnp_resource_change); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 1a8915e74160..816479ad217b 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -117,7 +117,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) return ACPI_FAILURE(status) ? -ENODEV : 0; } -struct pnp_protocol pnpacpi_protocol = { +static struct pnp_protocol pnpacpi_protocol = { .name = "Plug and Play ACPI", .get = pnpacpi_get_resources, .set = pnpacpi_set_resources, @@ -234,7 +234,7 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, } int pnpacpi_disabled __initdata; -int __init pnpacpi_init(void) +static int __init pnpacpi_init(void) { if (acpi_disabled || pnpacpi_disabled) { pnp_info("PnP ACPI: disabled"); @@ -258,4 +258,6 @@ static int __init pnpacpi_setup(char *str) } __setup("pnpacpi=", pnpacpi_setup); +#if 0 EXPORT_SYMBOL(pnpacpi_protocol); +#endif diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 887ad8939349..6ded527169f4 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -477,12 +477,14 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) } +#if 0 EXPORT_SYMBOL(pnp_register_dependent_option); EXPORT_SYMBOL(pnp_register_independent_option); EXPORT_SYMBOL(pnp_register_irq_resource); EXPORT_SYMBOL(pnp_register_dma_resource); EXPORT_SYMBOL(pnp_register_port_resource); EXPORT_SYMBOL(pnp_register_mem_resource); +#endif /* 0 */ /* format is: pnp_reserve_irq=irq1[,irq2] .... */ diff --git a/include/linux/pnp.h b/include/linux/pnp.h index aadbac29103c..584d57cb393a 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -353,7 +353,6 @@ struct pnp_protocol { int pnp_register_protocol(struct pnp_protocol *protocol); void pnp_unregister_protocol(struct pnp_protocol *protocol); int pnp_add_device(struct pnp_dev *dev); -void pnp_remove_device(struct pnp_dev *dev); int pnp_device_attach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev); extern struct list_head pnp_global; @@ -399,7 +398,6 @@ static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { } static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; } -static inline void pnp_remove_device(struct pnp_dev *dev) { } static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } -- cgit v1.2.3 From 3dead1a36069e0697a22ab9d623ac2c37247dfd0 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: enable cache support code for ColdFIre 5249 Enable the ColdFire 5249 cache support code - it should have been on. Also one more change of "extern inline" to "static inline". Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- include/asm-m68knommu/cacheflush.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h index 026bbc9565b4..49925e91e89c 100644 --- a/include/asm-m68knommu/cacheflush.h +++ b/include/asm-m68knommu/cacheflush.h @@ -25,7 +25,7 @@ #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ memcpy(dst, src, len) -extern inline void __flush_cache_all(void) +static inline void __flush_cache_all(void) { #ifdef CONFIG_M5407 /* @@ -64,7 +64,7 @@ extern inline void __flush_cache_all(void) "nop\n\t" : : : "d0" ); #endif /* CONFIG_M5272 */ -#if CONFIG_M5249 +#ifdef CONFIG_M5249 __asm__ __volatile__ ( "movel #0xa1000200, %%d0\n\t" "movec %%d0, %%CACR\n\t" -- cgit v1.2.3 From 2ed5e6d09e266bd2288d49aaaf240ed8c468c13c Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: move some platform irq support out of irq.h Move some of the m68knommu platform specific irq core support to its own header, irqnode.h. Having it in asm-m68knommu/irq.h causes some build pain, since it is included in a number of common code places (and not all the required definitions will be included at these places). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/asm-offsets.c | 1 + arch/m68knommu/platform/5307/ints.c | 1 + include/asm-m68knommu/irq.h | 31 ------------------------------- include/asm-m68knommu/irqnode.h | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 include/asm-m68knommu/irqnode.h (limited to 'include') diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c index cd3ffe12653e..b988c7bdc6e4 100644 --- a/arch/m68knommu/kernel/asm-offsets.c +++ b/arch/m68knommu/kernel/asm-offsets.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define DEFINE(sym, val) \ diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c index 0117754d44f3..a134fb2f0566 100644 --- a/arch/m68knommu/platform/5307/ints.c +++ b/arch/m68knommu/platform/5307/ints.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h index 208ccd969e4b..a08fa9b958da 100644 --- a/include/asm-m68knommu/irq.h +++ b/include/asm-m68knommu/irq.h @@ -2,7 +2,6 @@ #define _M68K_IRQ_H_ #include -#include #include #ifdef CONFIG_COLDFIRE @@ -82,36 +81,6 @@ extern void (*mach_disable_irq)(unsigned int); #endif /* CONFIG_M68360 */ -/* - * This structure is used to chain together the ISRs for a particular - * interrupt source (if it supports chaining). - */ -typedef struct irq_node { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; - struct irq_node *next; -} irq_node_t; - -/* - * This structure has only 4 elements for speed reasons - */ -typedef struct irq_handler { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; -} irq_handler_t; - -/* count of spurious interrupts */ -extern volatile unsigned int num_spurious; - -/* - * This function returns a new irq_node_t - */ -extern irq_node_t *new_irq_node(void); - /* * Some drivers want these entry points */ diff --git a/include/asm-m68knommu/irqnode.h b/include/asm-m68knommu/irqnode.h new file mode 100644 index 000000000000..a2503dfc554c --- /dev/null +++ b/include/asm-m68knommu/irqnode.h @@ -0,0 +1,36 @@ +#ifndef _M68K_IRQNODE_H_ +#define _M68K_IRQNODE_H_ + +#include + +/* + * This structure is used to chain together the ISRs for a particular + * interrupt source (if it supports chaining). + */ +typedef struct irq_node { + irqreturn_t (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; + struct irq_node *next; +} irq_node_t; + +/* + * This structure has only 4 elements for speed reasons + */ +typedef struct irq_handler { + irqreturn_t (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; +} irq_handler_t; + +/* count of spurious interrupts */ +extern volatile unsigned int num_spurious; + +/* + * This function returns a new irq_node_t + */ +extern irq_node_t *new_irq_node(void); + +#endif /* _M68K_IRQNODE_H_ */ -- cgit v1.2.3 From afc4841d8a0118fcce9fd520b21ec1da401603a3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 31 Oct 2005 00:30:39 +0000 Subject: Turn rtlx upside down. o Coding style o Race condition on open o Switch to dynamic major o Header file cleanup Signed-off-by: Ralf Baechle --- arch/mips/kernel/rtlx.c | 197 +++++++++++++++++++++++------------------------- include/asm-mips/rtlx.h | 28 +++---- 2 files changed, 105 insertions(+), 120 deletions(-) (limited to 'include') diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 8c81f3cb4e2d..1d855112bac2 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -20,42 +20,42 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include +#include #include #include -#include #include +#include -#define RTLX_MAJOR 64 #define RTLX_TARG_VPE 1 -struct rtlx_info *rtlx; +static struct rtlx_info *rtlx; static int major; static char module_name[] = "rtlx"; -static inline int spacefree(int read, int write, int size); +static struct irqaction irq; +static int irq_num; + +static inline int spacefree(int read, int write, int size) +{ + if (read == write) { + /* + * never fill the buffer completely, so indexes are always + * equal if empty and only empty, or !equal if data available + */ + return size - 1; + } + + return ((read + size - write) % size) - 1; +} static struct chan_waitqueues { wait_queue_head_t rt_queue; wait_queue_head_t lx_queue; } channel_wqs[RTLX_CHANNELS]; -static struct irqaction irq; -static int irq_num; - extern void *vpe_get_shared(int index); static void rtlx_dispatch(struct pt_regs *regs) @@ -63,9 +63,8 @@ static void rtlx_dispatch(struct pt_regs *regs) do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs); } -irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - irqreturn_t r = IRQ_HANDLED; int i; for (i = 0; i < RTLX_CHANNELS; i++) { @@ -75,30 +74,7 @@ irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) wake_up_interruptible(&channel_wqs[i].lx_queue); } - return r; -} - -void dump_rtlx(void) -{ - int i; - - printk("id 0x%lx state %d\n", rtlx->id, rtlx->state); - - for (i = 0; i < RTLX_CHANNELS; i++) { - struct rtlx_channel *chan = &rtlx->channel[i]; - - printk(" rt_state %d lx_state %d buffer_size %d\n", - chan->rt_state, chan->lx_state, chan->buffer_size); - - printk(" rt_read %d rt_write %d\n", - chan->rt_read, chan->rt_write); - - printk(" lx_read %d lx_write %d\n", - chan->lx_read, chan->lx_write); - - printk(" rt_buffer <%s>\n", chan->rt_buffer); - printk(" lx_buffer <%s>\n", chan->lx_buffer); - } + return IRQ_HANDLED; } /* call when we have the address of the shared structure from the SP side. */ @@ -108,7 +84,7 @@ static int rtlx_init(struct rtlx_info *rtlxi) if (rtlxi->id != RTLX_ID) { printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi); - return (-ENOEXEC); + return -ENOEXEC; } /* initialise the wait queues */ @@ -120,9 +96,8 @@ static int rtlx_init(struct rtlx_info *rtlxi) /* set up for interrupt handling */ memset(&irq, 0, sizeof(struct irqaction)); - if (cpu_has_vint) { + if (cpu_has_vint) set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); - } irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ; irq.handler = rtlx_interrupt; @@ -132,7 +107,8 @@ static int rtlx_init(struct rtlx_info *rtlxi) setup_irq(irq_num, &irq); rtlx = rtlxi; - return (0); + + return 0; } /* only allow one open process at a time to open each channel */ @@ -147,36 +123,36 @@ static int rtlx_open(struct inode *inode, struct file *filp) if (rtlx == NULL) { struct rtlx_info **p; if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { - printk(" vpe_get_shared is NULL. Has an SP program been loaded?\n"); - return (-EFAULT); + printk(KERN_ERR "vpe_get_shared is NULL. " + "Has an SP program been loaded?\n"); + return -EFAULT; } if (*p == NULL) { - printk(" vpe_shared %p %p\n", p, *p); - return (-EFAULT); + printk(KERN_ERR "vpe_shared %p %p\n", p, *p); + return -EFAULT; } if ((ret = rtlx_init(*p)) < 0) - return (ret); + return ret; } chan = &rtlx->channel[minor]; - /* already open? */ - if (chan->lx_state == RTLX_STATE_OPENED) - return (-EBUSY); + if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state)) + return -EBUSY; - chan->lx_state = RTLX_STATE_OPENED; - return (0); + return 0; } static int rtlx_release(struct inode *inode, struct file *filp) { - int minor; + int minor = MINOR(inode->i_rdev); - minor = MINOR(inode->i_rdev); - rtlx->channel[minor].lx_state = RTLX_STATE_UNUSED; - return (0); + clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state); + smp_mb__after_clear_bit(); + + return 0; } static unsigned int rtlx_poll(struct file *file, poll_table * wait) @@ -199,12 +175,13 @@ static unsigned int rtlx_poll(struct file *file, poll_table * wait) if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size)) mask |= POLLOUT | POLLWRNORM; - return (mask); + return mask; } static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { + unsigned long failed; size_t fl = 0L; int minor; struct rtlx_channel *lx; @@ -216,7 +193,7 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, /* data available? */ if (lx->lx_write == lx->lx_read) { if (file->f_flags & O_NONBLOCK) - return (0); // -EAGAIN makes cat whinge + return 0; /* -EAGAIN makes cat whinge */ /* go to sleep */ add_wait_queue(&channel_wqs[minor].lx_queue, &wait); @@ -232,39 +209,39 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, } /* find out how much in total */ - count = min( count, - (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size); + count = min(count, + (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size); /* then how much from the read pointer onwards */ - fl = min( count, (size_t)lx->buffer_size - lx->lx_read); + fl = min(count, (size_t)lx->buffer_size - lx->lx_read); - copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl); + failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl); + if (failed) { + count = fl - failed; + goto out; + } /* and if there is anything left at the beginning of the buffer */ - if ( count - fl ) - copy_to_user (buffer + fl, lx->lx_buffer, count - fl); + if (count - fl) { + failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl); + if (failed) { + count -= failed; + goto out; + } + } +out: /* update the index */ lx->lx_read += count; lx->lx_read %= lx->buffer_size; - return (count); -} - -static inline int spacefree(int read, int write, int size) -{ - if (read == write) { - /* never fill the buffer completely, so indexes are always equal if empty - and only empty, or !equal if data available */ - return (size - 1); - } - - return ((read + size - write) % size) - 1; + return count; } static ssize_t rtlx_write(struct file *file, const char __user * buffer, size_t count, loff_t * ppos) { + unsigned long failed; int minor; struct rtlx_channel *rt; size_t fl; @@ -277,7 +254,7 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer, if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) { if (file->f_flags & O_NONBLOCK) - return (-EAGAIN); + return -EAGAIN; add_wait_queue(&channel_wqs[minor].rt_queue, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -290,52 +267,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer, } /* total number of bytes to copy */ - count = min( count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) ); + count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) ); /* first bit from write pointer to the end of the buffer, or count */ fl = min(count, (size_t) rt->buffer_size - rt->rt_write); - copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl); + failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl); + if (failed) { + count = fl - failed; + goto out; + } /* if there's any left copy to the beginning of the buffer */ - if( count - fl ) - copy_from_user(rt->rt_buffer, buffer + fl, count - fl); + if (count - fl) { + failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl); + if (failed) { + count -= failed; + goto out; + } + } +out: rt->rt_write += count; rt->rt_write %= rt->buffer_size; - return(count); + return count; } static struct file_operations rtlx_fops = { - .owner = THIS_MODULE, - .open = rtlx_open, - .release = rtlx_release, - .write = rtlx_write, - .read = rtlx_read, - .poll = rtlx_poll + .owner = THIS_MODULE, + .open = rtlx_open, + .release = rtlx_release, + .write = rtlx_write, + .read = rtlx_read, + .poll = rtlx_poll }; -static int rtlx_module_init(void) +static char register_chrdev_failed[] __initdata = + KERN_ERR "rtlx_module_init: unable to register device\n"; + +static int __init rtlx_module_init(void) { - if ((major = register_chrdev(RTLX_MAJOR, module_name, &rtlx_fops)) < 0) { - printk("rtlx_module_init: unable to register device\n"); - return (-EBUSY); + major = register_chrdev(0, module_name, &rtlx_fops); + if (major < 0) { + printk(register_chrdev_failed); + return major; } - if (major == 0) - major = RTLX_MAJOR; - - return (0); + return 0; } -static void rtlx_module_exit(void) +static void __exit rtlx_module_exit(void) { unregister_chrdev(major, module_name); } module_init(rtlx_module_init); module_exit(rtlx_module_exit); + MODULE_DESCRIPTION("MIPS RTLX"); -MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc"); +MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc."); MODULE_LICENSE("GPL"); diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h index 83cdf6ab0d1f..1298c3fdf6c9 100644 --- a/include/asm-mips/rtlx.h +++ b/include/asm-mips/rtlx.h @@ -16,21 +16,19 @@ #define RTLX_ID (RTLX_xID | RTLX_VERSION) #define RTLX_CHANNELS 8 -enum rtlx_state { - RTLX_STATE_UNUSED = 0, - RTLX_STATE_INITIALISED, - RTLX_STATE_REMOTE_READY, - RTLX_STATE_OPENED -}; - #define RTLX_BUFFER_SIZE 1024 + +/* + * lx_state bits + */ +#define RTLX_STATE_OPENED 1UL + /* each channel supports read and write. linux (vpe0) reads lx_buffer and writes rt_buffer SP (vpe1) reads rt_buffer and writes lx_buffer */ -typedef struct rtlx_channel { - enum rtlx_state rt_state; - enum rtlx_state lx_state; +struct rtlx_channel { + unsigned long lx_state; int buffer_size; @@ -43,14 +41,12 @@ typedef struct rtlx_channel { void *queues; -} rtlx_channel_t; +}; -typedef struct rtlx_info { +struct rtlx_info { unsigned long id; - enum rtlx_state state; struct rtlx_channel channel[RTLX_CHANNELS]; +}; -} rtlx_info_t; - -#endif +#endif /* _RTLX_H_ */ -- cgit v1.2.3 From b0c705161f3088d384f755b0d92822a2214cba70 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 31 Oct 2005 00:33:01 +0000 Subject: Add spaces to MODULE_PROC_FAMILY values. Only a cosmetic fix to make the output of modinfo look readable. Signed-off-by: Ralf Baechle --- include/asm-mips/module.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h index 2be399311eec..2af496c78c12 100644 --- a/include/asm-mips/module.h +++ b/include/asm-mips/module.h @@ -76,43 +76,43 @@ search_module_dbetables(unsigned long addr) #endif #ifdef CONFIG_CPU_MIPS32_R1 -#define MODULE_PROC_FAMILY "MIPS32_R1" +#define MODULE_PROC_FAMILY "MIPS32_R1 " #elif defined CONFIG_CPU_MIPS32_R2 -#define MODULE_PROC_FAMILY "MIPS32_R2" +#define MODULE_PROC_FAMILY "MIPS32_R2 " #elif defined CONFIG_CPU_MIPS64_R1 -#define MODULE_PROC_FAMILY "MIPS64_R1" +#define MODULE_PROC_FAMILY "MIPS64_R1 " #elif defined CONFIG_CPU_MIPS64_R2 -#define MODULE_PROC_FAMILY "MIPS64_R2" +#define MODULE_PROC_FAMILY "MIPS64_R2 " #elif defined CONFIG_CPU_R3000 -#define MODULE_PROC_FAMILY "R3000" +#define MODULE_PROC_FAMILY "R3000 " #elif defined CONFIG_CPU_TX39XX -#define MODULE_PROC_FAMILY "TX39XX" +#define MODULE_PROC_FAMILY "TX39XX " #elif defined CONFIG_CPU_VR41XX -#define MODULE_PROC_FAMILY "VR41XX" +#define MODULE_PROC_FAMILY "VR41XX " #elif defined CONFIG_CPU_R4300 -#define MODULE_PROC_FAMILY "R4300" +#define MODULE_PROC_FAMILY "R4300 " #elif defined CONFIG_CPU_R4X00 -#define MODULE_PROC_FAMILY "R4X00" +#define MODULE_PROC_FAMILY "R4X00 " #elif defined CONFIG_CPU_TX49XX -#define MODULE_PROC_FAMILY "TX49XX" +#define MODULE_PROC_FAMILY "TX49XX " #elif defined CONFIG_CPU_R5000 -#define MODULE_PROC_FAMILY "R5000" +#define MODULE_PROC_FAMILY "R5000 " #elif defined CONFIG_CPU_R5432 -#define MODULE_PROC_FAMILY "R5432" +#define MODULE_PROC_FAMILY "R5432 " #elif defined CONFIG_CPU_R6000 -#define MODULE_PROC_FAMILY "R6000" +#define MODULE_PROC_FAMILY "R6000 " #elif defined CONFIG_CPU_NEVADA -#define MODULE_PROC_FAMILY "NEVADA" +#define MODULE_PROC_FAMILY "NEVADA " #elif defined CONFIG_CPU_R8000 -#define MODULE_PROC_FAMILY "R8000" +#define MODULE_PROC_FAMILY "R8000 " #elif defined CONFIG_CPU_R10000 -#define MODULE_PROC_FAMILY "R10000" +#define MODULE_PROC_FAMILY "R10000 " #elif defined CONFIG_CPU_RM7000 -#define MODULE_PROC_FAMILY "RM7000" +#define MODULE_PROC_FAMILY "RM7000 " #elif defined CONFIG_CPU_RM9000 -#define MODULE_PROC_FAMILY "RM9000" +#define MODULE_PROC_FAMILY "RM9000 " #elif defined CONFIG_CPU_SB1 -#define MODULE_PROC_FAMILY "SB1" +#define MODULE_PROC_FAMILY "SB1 " #else #error MODULE_PROC_FAMILY undefined for your processor configuration #endif -- cgit v1.2.3 From 08eaabfce0ba6eef7a0188888cc42f006914273e Mon Sep 17 00:00:00 2001 From: "Ilya A. Volynets-Evenbakh" Date: Wed, 26 Oct 2005 15:30:21 -0700 Subject: O2 parport definitions Signed-off-by: Ralf Baechle --- include/asm-mips/ip32/mace.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/ip32/mace.h b/include/asm-mips/ip32/mace.h index 432011b16c26..5bdc51d85b6c 100644 --- a/include/asm-mips/ip32/mace.h +++ b/include/asm-mips/ip32/mace.h @@ -147,6 +147,29 @@ struct mace_audio { } chan[3]; }; + +/* register definitions for parallel port DMA */ +struct mace_parport { +/* 0 - do nothing, 1 - pulse terminal count to the device after buffer is drained */ +#define MACEPAR_CONTEXT_LASTFLAG BIT(63) +/* Should not cross 4K page boundary */ +#define MACEPAR_CONTEXT_DATALEN_MASK 0xfff00000000 +/* Can be arbitrarily aligned on any byte boundary on output, 64 byte aligned on input */ +#define MACEPAR_CONTEXT_BASEADDR_MASK 0xffffffff + volatile u64 context_a; + volatile u64 context_b; +#define MACEPAR_CTLSTAT_DIRECTION BIT(0) /* 0 - mem->device, 1 - device->mem */ +#define MACEPAR_CTLSTAT_ENABLE BIT(1) /* 0 - channel frozen, 1 - channel enabled */ +#define MACEPAR_CTLSTAT_RESET BIT(2) /* 0 - channel active, 1 - complete channel reset */ +#define MACEPAR_CTLSTAT_CTXB_VALID BIT(3) +#define MACEPAR_CTLSTAT_CTXA_VALID BIT(4) + volatile u64 cntlstat; /* Control/Status register */ +#define MACEPAR_DIAG_CTXINUSE BIT(1) +#define MACEPAR_DIAG_DMACTIVE BIT(2) /* 1 - Dma engine is enabled and processing something */ +#define MACEPAR_DIAG_CTRMASK 0x3ffc /* Counter of bytes left */ + volatile u64 diagnostic; /* RO: diagnostic register */ +}; + /* ISA Control and DMA registers */ struct mace_isactrl { volatile unsigned long ringbase; @@ -199,6 +222,7 @@ struct mace_isactrl { volatile unsigned long _pad[0x2000/8 - 4]; volatile unsigned long dp_ram[0x400]; + struct mace_parport parport; }; /* Keyboard & Mouse registers @@ -277,7 +301,7 @@ struct mace_perif { */ /* Parallel port */ -struct mace_parallel { /* later... */ +struct mace_parallel { }; struct mace_ecp1284 { /* later... */ -- cgit v1.2.3 From 15b96a475706bfac71697a5d2f256750bdf749d3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Nov 2005 18:05:37 +0000 Subject: Add .gitignore files for MIPS. --- arch/mips/boot/.gitignore | 4 ++++ include/asm-mips/.gitignore | 1 + 2 files changed, 5 insertions(+) create mode 100644 arch/mips/boot/.gitignore create mode 100644 include/asm-mips/.gitignore (limited to 'include') diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore new file mode 100644 index 000000000000..ba63401c6e10 --- /dev/null +++ b/arch/mips/boot/.gitignore @@ -0,0 +1,4 @@ +mkboot +elf2ecoff +zImage +zImage.tmp diff --git a/include/asm-mips/.gitignore b/include/asm-mips/.gitignore new file mode 100644 index 000000000000..4ec57ad5bc3c --- /dev/null +++ b/include/asm-mips/.gitignore @@ -0,0 +1 @@ +asm_offsets.h -- cgit v1.2.3 From e329331aedeca0f2a7e15bd26a829ee1619c05e0 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 3 Nov 2005 01:02:40 +0900 Subject: Remove mips_rtc_lock The mips_rtc_lock is no longer needed because RTC operations should be protected already by other mechanism. (rtc_lock, local_irq_save, etc.) Also, locking whole rtc_get_time/rtc_set_time should be avoided while some RTC routines might take very long time (a few seconds). Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/rtc.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'include') diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h index a60e0dc7c9b9..a2abc4572b63 100644 --- a/include/asm-mips/rtc.h +++ b/include/asm-mips/rtc.h @@ -14,7 +14,6 @@ #ifdef __KERNEL__ -#include #include #include @@ -29,17 +28,13 @@ #define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ #define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ -static DEFINE_SPINLOCK(mips_rtc_lock); - static inline unsigned int get_rtc_time(struct rtc_time *time) { unsigned long nowtime; - spin_lock(&mips_rtc_lock); nowtime = rtc_get_time(); to_tm(nowtime, time); time->tm_year -= 1900; - spin_unlock(&mips_rtc_lock); return RTC_24H; } @@ -49,12 +44,10 @@ static inline int set_rtc_time(struct rtc_time *time) unsigned long nowtime; int ret; - spin_lock(&mips_rtc_lock); nowtime = mktime(time->tm_year+1900, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); ret = rtc_set_time(nowtime); - spin_unlock(&mips_rtc_lock); return ret; } -- cgit v1.2.3 From 53c2df2f4ebbc1d8231ca7cc13ac5381230888b1 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 3 Nov 2005 01:01:15 +0900 Subject: Use rtc_lock to protect RTC operations Many RTC routines were not protected against each other, so there are potential races, for example, ntp-update against /dev/rtc. This patch fixes them using rtc_lock. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/ddb5xxx/common/rtc_ds1386.c | 6 ++++++ arch/mips/dec/time.c | 24 ++++++++++++++++++++++-- arch/mips/jmr3927/common/rtc_ds1742.c | 6 ++++++ arch/mips/lasat/ds1603.c | 9 +++++++++ arch/mips/momentum/jaguar_atx/setup.c | 6 ++++++ arch/mips/momentum/ocelot_3/setup.c | 6 ++++++ arch/mips/momentum/ocelot_c/setup.c | 6 ++++++ arch/mips/pmc-sierra/yosemite/setup.c | 6 ++++++ arch/mips/sgi-ip22/ip22-time.c | 6 ++++++ arch/mips/sibyte/swarm/rtc_m41t81.c | 7 +++++++ arch/mips/sibyte/swarm/rtc_xicor1241.c | 6 ++++++ include/asm-mips/mc146818-time.h | 24 ++++++++++++++++++++++-- include/asm-mips/time.h | 3 +++ 13 files changed, 111 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c index f5b11508ff2f..995896ac0e39 100644 --- a/arch/mips/ddb5xxx/common/rtc_ds1386.c +++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c @@ -41,7 +41,9 @@ rtc_ds1386_get_time(void) u8 byte; u8 temp; unsigned int year, month, day, hour, minute, second; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; @@ -60,6 +62,7 @@ rtc_ds1386_get_time(void) /* enable time transfer */ byte |= 0x80; WRITE_RTC(0xB, byte); + spin_unlock_irqrestore(&rtc_lock, flags); /* calc hour */ if (temp & 0x40) { @@ -81,7 +84,9 @@ rtc_ds1386_set_time(unsigned long t) u8 byte; u8 temp; u8 year, month, day, hour, minute, second; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; @@ -133,6 +138,7 @@ rtc_ds1386_set_time(unsigned long t) if (second != READ_RTC(0x1)) { WRITE_RTC(0x1, second); } + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index dc7091caa7aa..174822344131 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -37,10 +37,25 @@ #include +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char dec_rtc_is_updating(void) +{ + unsigned char uip; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + spin_unlock_irqrestore(&rtc_lock, flags); + return uip; +} + static unsigned long dec_rtc_get_time(void) { unsigned int year, mon, day, hour, min, sec, real_year; int i; + unsigned long flags; /* The Linux interpretation of the DS1287 clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the @@ -49,11 +64,12 @@ static unsigned long dec_rtc_get_time(void) */ /* read RTC exactly on falling edge of update flag */ for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + if (dec_rtc_is_updating()) break; for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + if (!dec_rtc_is_updating()) break; + spin_lock_irqsave(&rtc_lock, flags); /* Isn't this overkill? UIP above should guarantee consistency */ do { sec = CMOS_READ(RTC_SECONDS); @@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void) * of unused BBU RAM locations. */ real_year = CMOS_READ(RTC_DEC_YEAR); + spin_unlock_irqrestore(&rtc_lock, flags); year += real_year - 72 + 2000; return mktime(year, mon, day, hour, min, sec); @@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + /* irq are locally disabled here */ + spin_lock(&rtc_lock); /* tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); @@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime) */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock(&rtc_lock); return retval; } diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c index 1ae4318e1358..8b407d7dc460 100644 --- a/arch/mips/jmr3927/common/rtc_ds1742.c +++ b/arch/mips/jmr3927/common/rtc_ds1742.c @@ -57,7 +57,9 @@ rtc_ds1742_get_time(void) { unsigned int year, month, day, hour, minute, second; unsigned int century; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); CMOS_WRITE(RTC_READ, RTC_CONTROL); second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); @@ -67,6 +69,7 @@ rtc_ds1742_get_time(void) year = BCD2BIN(CMOS_READ(RTC_YEAR)); century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); CMOS_WRITE(0, RTC_CONTROL); + spin_unlock_irqrestore(&rtc_lock, flags); year += century * 100; @@ -81,7 +84,9 @@ rtc_ds1742_set_time(unsigned long t) u8 year, month, day, hour, minute, second; u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; int cmos_century; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); CMOS_WRITE(RTC_READ, RTC_CONTROL); cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); cmos_minute = (u8)CMOS_READ(RTC_MINUTES); @@ -139,6 +144,7 @@ rtc_ds1742_set_time(unsigned long t) /* RTC_CENTURY and RTC_CONTROL share same address... */ CMOS_WRITE(cmos_century, RTC_CONTROL); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c index 9d7812e03dcd..7dced67c55eb 100644 --- a/arch/mips/lasat/ds1603.c +++ b/arch/mips/lasat/ds1603.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "ds1603.h" @@ -138,19 +139,27 @@ static void rtc_end_op(void) unsigned long ds1603_read(void) { unsigned long word; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); rtc_init_op(); rtc_write_byte(READ_TIME_CMD); word = rtc_read_word(); rtc_end_op(); + spin_unlock_irqrestore(&rtc_lock, flags); return word; } int ds1603_set(unsigned long time) { + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); rtc_init_op(); rtc_write_byte(SET_TIME_CMD); rtc_write_word(time); rtc_end_op(); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 768bf4406452..bab192ddc185 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -149,7 +149,9 @@ arch_initcall(per_cpu_mappings); unsigned long m48t37y_get_time(void) { unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* stop the update */ rtc_base[0x7ff8] = 0x40; @@ -166,6 +168,7 @@ unsigned long m48t37y_get_time(void) /* start the update */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -173,11 +176,13 @@ unsigned long m48t37y_get_time(void) int m48t37y_set_time(unsigned long sec) { struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ rtc_base[0x7ff8] = 0x80; @@ -201,6 +206,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index a7803e08f9db..c9b7ff8148ec 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c @@ -135,7 +135,9 @@ void setup_wired_tlb_entries(void) unsigned long m48t37y_get_time(void) { unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* stop the update */ rtc_base[0x7ff8] = 0x40; @@ -152,6 +154,7 @@ unsigned long m48t37y_get_time(void) /* start the update */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -159,11 +162,13 @@ unsigned long m48t37y_get_time(void) int m48t37y_set_time(unsigned long sec) { struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ rtc_base[0x7ff8] = 0x80; @@ -187,6 +192,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index ce70fc96f160..2755c1547473 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -140,7 +140,9 @@ unsigned long m48t37y_get_time(void) unsigned char* rtc_base = (unsigned char*)0xfc800000; #endif unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* stop the update */ rtc_base[0x7ff8] = 0x40; @@ -157,6 +159,7 @@ unsigned long m48t37y_get_time(void) /* start the update */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -169,11 +172,13 @@ int m48t37y_set_time(unsigned long sec) unsigned char* rtc_base = (unsigned char*)0xfc800000; #endif struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ rtc_base[0x7ff8] = 0x80; @@ -197,6 +202,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index bdc2ab55bed6..059755b5ed57 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -73,7 +73,9 @@ void __init bus_error_init(void) unsigned long m48t37y_get_time(void) { unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* Stop the update to the time */ m48t37_base->control = 0x40; @@ -88,6 +90,7 @@ unsigned long m48t37y_get_time(void) /* Start the update to the time again */ m48t37_base->control = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -95,11 +98,13 @@ unsigned long m48t37y_get_time(void) int m48t37y_set_time(unsigned long sec) { struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ m48t37_base->control = 0x80; @@ -123,6 +128,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ m48t37_base->control = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index df9b5694328a..b7300cc5c5ad 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c @@ -35,7 +35,9 @@ static unsigned long indy_rtc_get_time(void) { unsigned int yrs, mon, day, hrs, min, sec; unsigned int save_control; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; @@ -47,6 +49,7 @@ static unsigned long indy_rtc_get_time(void) yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); hpc3c0->rtcregs[RTC_CMD] = save_control; + spin_unlock_irqrestore(&rtc_lock, flags); if (yrs < 45) yrs += 30; @@ -60,6 +63,7 @@ static int indy_rtc_set_time(unsigned long tim) { struct rtc_time tm; unsigned int save_control; + unsigned long flags; to_tm(tim, &tm); @@ -68,6 +72,7 @@ static int indy_rtc_set_time(unsigned long tim) if (tm.tm_year >= 100) tm.tm_year -= 100; + spin_lock_irqsave(&rtc_lock, flags); save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; @@ -80,6 +85,7 @@ static int indy_rtc_set_time(unsigned long tim) hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; hpc3c0->rtcregs[RTC_CMD] = save_control; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c index 5b4fc26c1b36..c13914bdda59 100644 --- a/arch/mips/sibyte/swarm/rtc_m41t81.c +++ b/arch/mips/sibyte/swarm/rtc_m41t81.c @@ -144,6 +144,7 @@ static int m41t81_write(uint8_t addr, int b) int m41t81_set_time(unsigned long t) { struct rtc_time tm; + unsigned long flags; to_tm(t, &tm); @@ -153,6 +154,7 @@ int m41t81_set_time(unsigned long t) * believe we should finish writing min within a second. */ + spin_lock_irqsave(&rtc_lock, flags); tm.tm_sec = BIN2BCD(tm.tm_sec); m41t81_write(M41T81REG_SC, tm.tm_sec); @@ -180,6 +182,7 @@ int m41t81_set_time(unsigned long t) tm.tm_year %= 100; tm.tm_year = BIN2BCD(tm.tm_year); m41t81_write(M41T81REG_YR, tm.tm_year); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } @@ -187,19 +190,23 @@ int m41t81_set_time(unsigned long t) unsigned long m41t81_get_time(void) { unsigned int year, mon, day, hour, min, sec; + unsigned long flags; /* * min is valid if two reads of sec are the same. */ for (;;) { + spin_lock_irqsave(&rtc_lock, flags); sec = m41t81_read(M41T81REG_SC); min = m41t81_read(M41T81REG_MN); if (sec == m41t81_read(M41T81REG_SC)) break; + spin_unlock_irqrestore(&rtc_lock, flags); } hour = m41t81_read(M41T81REG_HR) & 0x3f; day = m41t81_read(M41T81REG_DT); mon = m41t81_read(M41T81REG_MO); year = m41t81_read(M41T81REG_YR); + spin_unlock_irqrestore(&rtc_lock, flags); sec = BCD2BIN(sec); min = BCD2BIN(min); diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c index d9ff9323f24e..f4a178836415 100644 --- a/arch/mips/sibyte/swarm/rtc_xicor1241.c +++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c @@ -113,9 +113,11 @@ int xicor_set_time(unsigned long t) { struct rtc_time tm; int tmp; + unsigned long flags; to_tm(t, &tm); + spin_lock_irqsave(&rtc_lock, flags); /* unlock writes to the CCR */ xicor_write(X1241REG_SR, X1241REG_SR_WEL); xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); @@ -160,6 +162,7 @@ int xicor_set_time(unsigned long t) xicor_write(X1241REG_HR, tmp); xicor_write(X1241REG_SR, 0); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } @@ -167,7 +170,9 @@ int xicor_set_time(unsigned long t) unsigned long xicor_get_time(void) { unsigned int year, mon, day, hour, min, sec, y2k; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); sec = xicor_read(X1241REG_SC); min = xicor_read(X1241REG_MN); hour = xicor_read(X1241REG_HR); @@ -183,6 +188,7 @@ unsigned long xicor_get_time(void) mon = xicor_read(X1241REG_MO); year = xicor_read(X1241REG_YR); y2k = xicor_read(X1241REG_Y2K); + spin_unlock_irqrestore(&rtc_lock, flags); sec = BCD2BIN(sec); min = BCD2BIN(min); diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h index a2c2d2c24303..47214861093b 100644 --- a/include/asm-mips/mc146818-time.h +++ b/include/asm-mips/mc146818-time.h @@ -33,7 +33,9 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; int retval = 0; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -79,14 +81,30 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock_irqrestore(&rtc_lock, flags); return retval; } +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char rtc_is_updating(void) +{ + unsigned char uip; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + spin_unlock_irqrestore(&rtc_lock, flags); + return uip; +} + static inline unsigned long mc146818_get_cmos_time(void) { unsigned int year, mon, day, hour, min, sec; int i; + unsigned long flags; /* * The Linux interpretation of the CMOS clock register contents: @@ -97,12 +115,13 @@ static inline unsigned long mc146818_get_cmos_time(void) /* read RTC exactly on falling edge of update flag */ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + if (rtc_is_updating()) break; for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + if (!rtc_is_updating()) break; + spin_lock_irqsave(&rtc_lock, flags); do { /* Isn't this overkill ? UIP above should guarantee consistency */ sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); @@ -120,6 +139,7 @@ static inline unsigned long mc146818_get_cmos_time(void) BCD_TO_BIN(mon); BCD_TO_BIN(year); } + spin_unlock_irqrestore(&rtc_lock, flags); year = mc146818_decode_year(year); return mktime(year, mon, day, hour, min, sec); diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index e22a20665871..9cc3564cc2c9 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -20,6 +20,9 @@ #include #include #include +#include + +extern spinlock_t rtc_lock; /* * RTC ops. By default, they point to no-RTC functions. -- cgit v1.2.3 From a0f08209c685b4f7dccaf013da74e0e80986c477 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 5 Nov 2005 02:02:54 +0900 Subject: Define MAX_UDELAY_MS If HZ was 1000, mdelay(2) cause overflow on multiplication in __udelay. We should define MAX_UDELAY_MS properly to prevent this. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/delay.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h index 85435a8d4e52..48d00cccdafa 100644 --- a/include/asm-mips/delay.h +++ b/include/asm-mips/delay.h @@ -84,4 +84,13 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj) #define udelay(usecs) __udelay((usecs),__udelay_val) +/* make sure "usecs *= ..." in udelay do not overflow. */ +#if HZ >= 1000 +#define MAX_UDELAY_MS 1 +#elif HZ <= 200 +#define MAX_UDELAY_MS 5 +#else +#define MAX_UDELAY_MS (1000 / HZ) +#endif + #endif /* _ASM_DELAY_H */ -- cgit v1.2.3 From 4fa0997be8050ea34f117f813d3aafa7956a5711 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Nov 2005 15:36:44 +0000 Subject: Delete duplicate definitions. This reverts 8f91ed6c2fec8cb746e4dc86a79247162b4c5a7a. Signed-off-by: Ralf Baechle --- include/asm-mips/errno.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h index 9d3e6e7cdb92..3c0d840e4577 100644 --- a/include/asm-mips/errno.h +++ b/include/asm-mips/errno.h @@ -119,10 +119,6 @@ #define EOWNERDEAD 165 /* Owner died */ #define ENOTRECOVERABLE 166 /* State not recoverable */ -/* for robust mutexes */ -#define EOWNERDEAD 165 /* Owner died */ -#define ENOTRECOVERABLE 166 /* State not recoverable */ - #define EDQUOT 1133 /* Quota exceeded */ #ifdef __KERNEL__ -- cgit v1.2.3 From a06d61c648890ad7e86d5ea04bd6999b254db193 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 6 Nov 2005 23:58:21 +0900 Subject: Redefine outs[wl] for ide_outs[wl]. Add missing bits to fix D-cache aliasing problem in the PIO IDE driver. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/mach-generic/ide.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h index 961006948c7c..550979a9ea9d 100644 --- a/include/asm-mips/mach-generic/ide.h +++ b/include/asm-mips/mach-generic/ide.h @@ -168,8 +168,12 @@ static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count) /* ide_insw calls insw, not __ide_insw. Why? */ #undef insw #undef insl +#undef outsw +#undef outsl #define insw(port, addr, count) __ide_insw(port, addr, count) #define insl(port, addr, count) __ide_insl(port, addr, count) +#define outsw(port, addr, count) __ide_outsw(port, addr, count) +#define outsl(port, addr, count) __ide_outsl(port, addr, count) #endif /* __KERNEL__ */ -- cgit v1.2.3 From 9b1283bedd6b8fe2f4dfc47705d6cea1b5e2d853 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 21:01:06 +0000 Subject: [ARM] Add support for Realview with MPcore tile Add uniprocessor support for Realview platform fitted with the MPcore (SMP) tile. Signed-off-by: Russell King --- arch/arm/mach-realview/Kconfig | 9 ++++++ arch/arm/mach-realview/realview_eb.c | 5 +++ include/asm-arm/arch-realview/platform.h | 55 ++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) (limited to 'include') diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 4b63dc9eabfe..129976866d47 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -8,4 +8,13 @@ config MACH_REALVIEW_EB help Include support for the ARM(R) RealView Emulation Baseboard platform. +config REALVIEW_MPCORE + bool "Support MPcore tile" + depends on MACH_REALVIEW_EB + help + Enable support for the MPCore tile on the Realview platform. + Since there are device address and interrupt differences, a + kernel built with this option enabled is not compatible with + other tiles. + endmenu diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 267bb07e39b7..7dc32503fdf2 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -136,6 +136,11 @@ static struct amba_device *amba_devs[] __initdata = { static void __init gic_init_irq(void) { +#ifdef CONFIG_REALVIEW_MPCORE + writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); + writel(0x008003c0, __io_address(REALVIEW_SYS_BASE) + 0xd8); + writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); +#endif gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE)); gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); } diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index 4b6de13a6b9a..432260121c8b 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -203,8 +203,13 @@ /* Reserved 0x1001A000 - 0x1001FFFF */ #define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */ #define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */ +#ifndef CONFIG_REALVIEW_MPCORE #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ +#else +#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ +#endif #define REALVIEW_SMC_BASE 0x10080000 /* SMC */ /* Reserved 0x10090000 - 0x100EFFFF */ @@ -265,6 +270,7 @@ * Interrupts - bit assignment (primary) * ------------------------------------------------------------------------ */ +#ifndef CONFIG_REALVIEW_MPCORE #define INT_WDOGINT 0 /* Watchdog timer */ #define INT_SOFTINT 1 /* Software interrupt */ #define INT_COMMRx 2 /* Debug Comm Rx interrupt */ @@ -297,6 +303,55 @@ #define INT_USB 29 /* USB controller */ #define INT_TSPENINT 30 /* Touchscreen pen */ #define INT_TSKPADINT 31 /* Touchscreen keypad */ +#else +#define INT_LOCALTIMER 29 +#define INT_LOCALWDOG 30 + +#define INT_AACI 0 +#define INT_TIMERINT0_1 1 +#define INT_TIMERINT2_3 2 +#define INT_USB 3 +#define INT_UARTINT0 4 +#define INT_UARTINT1 5 +#define INT_RTCINT 6 +#define INT_KMI0 7 +#define INT_KMI1 8 +#define INT_ETH 9 +#define INT_EB_IRQ1 10 /* main GIC */ +#define INT_EB_IRQ2 11 /* tile GIC */ +#define INT_EB_FIQ1 12 /* main GIC */ +#define INT_EB_FIQ2 13 /* tile GIC */ +#define INT_MMCI0A 14 +#define INT_MMCI0B 15 + +#define INT_PMU_CPU0 17 +#define INT_PMU_CPU1 18 +#define INT_PMU_CPU2 19 +#define INT_PMU_CPU3 20 +#define INT_PMU_SCU0 21 +#define INT_PMU_SCU1 22 +#define INT_PMU_SCU2 23 +#define INT_PMU_SCU3 24 +#define INT_PMU_SCU4 25 +#define INT_PMU_SCU5 26 +#define INT_PMU_SCU6 27 +#define INT_PMU_SCU7 28 + +#define INT_L220_EVENT 29 +#define INT_L220_SLAVE 30 +#define INT_L220_DECODE 31 + +#define INT_UARTINT2 -1 +#define INT_UARTINT3 -1 +#define INT_CLCDINT -1 +#define INT_DMAINT -1 +#define INT_WDOGINT -1 +#define INT_GPIOINT0 -1 +#define INT_GPIOINT1 -1 +#define INT_GPIOINT2 -1 +#define INT_SCIINT -1 +#define INT_SSPINT -1 +#endif /* * Interrupt bit positions -- cgit v1.2.3 From 862184fe013146a0d9654a5598c5a2691747541c Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 21:05:42 +0000 Subject: [ARM SMP] Add Realview MPcore SMP support Add SMP support for the MPcore tile fitted to the Realview ARM platform. Signed-off-by: Russell King --- arch/arm/mach-realview/Makefile | 1 + arch/arm/mach-realview/headsmp.S | 39 ++++++ arch/arm/mach-realview/platsmp.c | 195 ++++++++++++++++++++++++++++ arch/arm/mm/proc-v6.S | 18 +++ include/asm-arm/arch-realview/entry-macro.S | 14 ++ include/asm-arm/arch-realview/platform.h | 1 + include/asm-arm/arch-realview/smp.h | 31 +++++ include/asm-arm/hardware/arm_scu.h | 13 ++ 8 files changed, 312 insertions(+) create mode 100644 arch/arm/mach-realview/headsmp.S create mode 100644 arch/arm/mach-realview/platsmp.c create mode 100644 include/asm-arm/arch-realview/smp.h create mode 100644 include/asm-arm/hardware/arm_scu.h (limited to 'include') diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 8d37ea1605fd..011a85c10627 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -4,3 +4,4 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-realview/headsmp.S b/arch/arm/mach-realview/headsmp.S new file mode 100644 index 000000000000..4075473cf68a --- /dev/null +++ b/arch/arm/mach-realview/headsmp.S @@ -0,0 +1,39 @@ +/* + * linux/arch/arm/mach-realview/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * 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 + + __INIT + +/* + * Realview specific entry point for secondary CPUs. This provides + * a "holding pen" into which all secondary cores are held until we're + * ready for them to initialise. + */ +ENTRY(realview_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + +1: .long . + .long pen_release diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c new file mode 100644 index 000000000000..9844644d0fb5 --- /dev/null +++ b/arch/arm/mach-realview/platsmp.c @@ -0,0 +1,195 @@ +/* + * linux/arch/arm/mach-realview/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * 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 "core.h" + +extern void realview_secondary_startup(void); + +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ +volatile int __cpuinitdata pen_release = -1; + +static unsigned int __init get_core_count(void) +{ + unsigned int ncores; + + ncores = __raw_readl(IO_ADDRESS(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG); + + return (ncores & 0x03) + 1; +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + /* + * the primary core may have used a "cross call" soft interrupt + * to get this processor out of WFI in the BootMonitor - make + * sure that we are no longer being sent this soft interrupt + */ + smp_cross_call_done(cpumask_of_cpu(cpu)); + + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + pen_release = cpu; + flush_cache_all(); + + /* + * XXX + * + * This is a later addition to the booting protocol: the + * bootMonitor now puts secondary cores into WFI, so + * poke_milo() no longer gets the cores moving; we need + * to send a soft interrupt to wake the secondary core. + * Use smp_cross_call() for this, since there's little + * point duplicating the code here + */ + smp_cross_call(cpumask_of_cpu(cpu)); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +static void __init poke_milo(void) +{ + extern void secondary_startup(void); + + /* nobody is to be released from the pen yet */ + pen_release = -1; + + /* + * write the address of secondary startup into the system-wide + * flags register, then clear the bottom two bits, which is what + * BootMonitor is waiting for + */ +#if 1 +#define REALVIEW_SYS_FLAGSS_OFFSET 0x30 + __raw_writel(virt_to_phys(realview_secondary_startup), + (IO_ADDRESS(REALVIEW_SYS_BASE) + + REALVIEW_SYS_FLAGSS_OFFSET)); +#define REALVIEW_SYS_FLAGSC_OFFSET 0x34 + __raw_writel(3, + (IO_ADDRESS(REALVIEW_SYS_BASE) + + REALVIEW_SYS_FLAGSC_OFFSET)); +#endif + + mb(); +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int ncores = get_core_count(); + unsigned int cpu = smp_processor_id(); + int i; + + /* sanity check */ + if (ncores == 0) { + printk(KERN_ERR + "Realview: strange CM count of 0? Default to 1\n"); + + ncores = 1; + } + + if (ncores > NR_CPUS) { + printk(KERN_WARNING + "Realview: no. of cores (%d) greater than configured " + "maximum of %d - clipping\n", + ncores, NR_CPUS); + ncores = NR_CPUS; + } + + smp_store_cpu_info(cpu); + + /* + * are we trying to boot more cores than exist? + */ + if (max_cpus > ncores) + max_cpus = ncores; + + /* + * Initialise the possible/present maps. + * cpu_possible_map describes the set of CPUs which may be present + * cpu_present_map describes the set of CPUs populated + */ + for (i = 0; i < max_cpus; i++) { + cpu_set(i, cpu_possible_map); + cpu_set(i, cpu_present_map); + } + + /* + * Do we need any more CPUs? If so, then let them know where + * to start. Note that, on modern versions of MILO, the "poke" + * doesn't actually do anything until each individual core is + * sent a soft interrupt to get it out of WFI + */ + if (max_cpus > 1) + poke_milo(); +} diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index a39d8fa2ede5..92f3ca31b7b9 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -194,6 +195,23 @@ cpu_v6_name: * - cache type register is implemented */ __v6_setup: +#ifdef CONFIG_SMP + /* Set up the SCU on core 0 only */ + mrc p15, 0, r0, c0, c0, 5 @ CPU core number + ands r0, r0, #15 + moveq r0, #0x10000000 @ SCU_BASE + orreq r0, r0, #0x00100000 + ldreq r5, [r0, #SCU_CTRL] + orreq r5, r5, #1 + streq r5, [r0, #SCU_CTRL] + +#ifndef CONFIG_CPU_DCACHE_DISABLE + mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode + orr r0, r0, #0x20 + mcr p15, 0, r0, c1, c0, 1 +#endif +#endif + mov r0, #0 mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S index 2712ba77bb3a..4df469bf42e2 100644 --- a/include/asm-arm/arch-realview/entry-macro.S +++ b/include/asm-arm/arch-realview/entry-macro.S @@ -47,3 +47,17 @@ cmpcs \irqnr, \irqnr .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index 432260121c8b..aef9b36b3c37 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -207,6 +207,7 @@ #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ #else +#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ #define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ #endif diff --git a/include/asm-arm/arch-realview/smp.h b/include/asm-arm/arch-realview/smp.h new file mode 100644 index 000000000000..fc87783e8e8b --- /dev/null +++ b/include/asm-arm/arch-realview/smp.h @@ -0,0 +1,31 @@ +#ifndef ASMARM_ARCH_SMP_H +#define ASMARM_ARCH_SMP_H + +#include + +#include + +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5" \ + : "=r" (cpunum)); \ + cpunum &= 0x0F; \ + }) + +/* + * We use IRQ1 as the IPI + */ +static inline void smp_cross_call(cpumask_t callmap) +{ + gic_raise_softirq(callmap, 1); +} + +/* + * Do nothing on MPcore. + */ +static inline void smp_cross_call_done(cpumask_t callmap) +{ +} + +#endif diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h new file mode 100644 index 000000000000..9903f60c84b7 --- /dev/null +++ b/include/asm-arm/hardware/arm_scu.h @@ -0,0 +1,13 @@ +#ifndef ASMARM_HARDWARE_ARM_SCU_H +#define ASMARM_HARDWARE_ARM_SCU_H + +/* + * SCU registers + */ +#define SCU_CTRL 0x00 +#define SCU_CONFIG 0x04 +#define SCU_CPU_STATUS 0x08 +#define SCU_INVALIDATE 0x0c +#define SCU_FPGA_REVISION 0x10 + +#endif -- cgit v1.2.3 From dedeb0029b9c83420fc1337d4ee53daa7b2a0ad4 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 7 Nov 2005 14:09:01 -0800 Subject: [SPARC64] mm: context switch ptlock sparc64 is unique among architectures in taking the page_table_lock in its context switch (well, cris does too, but erroneously, and it's not yet SMP anyway). This seems to be a private affair between switch_mm and activate_mm, using page_table_lock as a per-mm lock, without any relation to its uses elsewhere. That's fine, but comment it as such; and unlock sooner in switch_mm, more like in activate_mm (preemption is disabled here). There is a block of "if (0)"ed code in smp_flush_tlb_pending which would have liked to rely on the page_table_lock, in switch_mm and elsewhere; but its comment explains how dup_mmap's flush_tlb_mm defeated it. And though that could have been changed at any time over the past few years, now the chance vanishes as we push the page_table_lock downwards, and perhaps split it per page table page. Just delete that block of code. Which leaves the mysterious spin_unlock_wait(&oldmm->page_table_lock) in kernel/fork.c copy_mm. Textual analysis (supported by Nick Piggin) suggests that the comment was written by DaveM, and that it relates to the defeated approach in the sparc64 smp_flush_tlb_pending. Just delete this block too. Signed-off-by: Hugh Dickins Signed-off-by: David S. Miller --- arch/sparc64/kernel/smp.c | 31 +++++--------------------- include/asm-sparc64/mmu_context.h | 46 ++++++++++++++++++++------------------- kernel/fork.c | 7 ------ 3 files changed, 29 insertions(+), 55 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index b137fd63f5e1..a9089e2140e9 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -883,34 +883,13 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long u32 ctx = CTX_HWBITS(mm->context); int cpu = get_cpu(); - if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) mm->cpu_vm_mask = cpumask_of_cpu(cpu); - goto local_flush_and_out; - } else { - /* This optimization is not valid. Normally - * we will be holding the page_table_lock, but - * there is an exception which is copy_page_range() - * when forking. The lock is held during the individual - * page table updates in the parent, but not at the - * top level, which is where we are invoked. - */ - if (0) { - cpumask_t this_cpu_mask = cpumask_of_cpu(cpu); - - /* By virtue of running under the mm->page_table_lock, - * and mmu_context.h:switch_mm doing the same, the - * following operation is safe. - */ - if (cpus_equal(mm->cpu_vm_mask, this_cpu_mask)) - goto local_flush_and_out; - } - } - - smp_cross_call_masked(&xcall_flush_tlb_pending, - ctx, nr, (unsigned long) vaddrs, - mm->cpu_vm_mask); + else + smp_cross_call_masked(&xcall_flush_tlb_pending, + ctx, nr, (unsigned long) vaddrs, + mm->cpu_vm_mask); -local_flush_and_out: __flush_tlb_pending(ctx, nr, vaddrs); put_cpu(); diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index 87c43c67866e..08ba72d7722c 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h @@ -87,37 +87,35 @@ extern void __flush_tlb_mm(unsigned long, unsigned long); static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk) { unsigned long ctx_valid; + int cpu; + /* Note: page_table_lock is used here to serialize switch_mm + * and activate_mm, and their calls to get_new_mmu_context. + * This use of page_table_lock is unrelated to its other uses. + */ spin_lock(&mm->page_table_lock); - if (CTX_VALID(mm->context)) - ctx_valid = 1; - else - ctx_valid = 0; + ctx_valid = CTX_VALID(mm->context); + if (!ctx_valid) + get_new_mmu_context(mm); + spin_unlock(&mm->page_table_lock); if (!ctx_valid || (old_mm != mm)) { - if (!ctx_valid) - get_new_mmu_context(mm); - load_secondary_context(mm); reload_tlbmiss_state(tsk, mm); } - { - int cpu = smp_processor_id(); - - /* Even if (mm == old_mm) we _must_ check - * the cpu_vm_mask. If we do not we could - * corrupt the TLB state because of how - * smp_flush_tlb_{page,range,mm} on sparc64 - * and lazy tlb switches work. -DaveM - */ - if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) { - cpu_set(cpu, mm->cpu_vm_mask); - __flush_tlb_mm(CTX_HWBITS(mm->context), - SECONDARY_CONTEXT); - } + /* Even if (mm == old_mm) we _must_ check + * the cpu_vm_mask. If we do not we could + * corrupt the TLB state because of how + * smp_flush_tlb_{page,range,mm} on sparc64 + * and lazy tlb switches work. -DaveM + */ + cpu = smp_processor_id(); + if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) { + cpu_set(cpu, mm->cpu_vm_mask); + __flush_tlb_mm(CTX_HWBITS(mm->context), + SECONDARY_CONTEXT); } - spin_unlock(&mm->page_table_lock); } #define deactivate_mm(tsk,mm) do { } while (0) @@ -127,6 +125,10 @@ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm { int cpu; + /* Note: page_table_lock is used here to serialize switch_mm + * and activate_mm, and their calls to get_new_mmu_context. + * This use of page_table_lock is unrelated to its other uses. + */ spin_lock(&mm->page_table_lock); if (!CTX_VALID(mm->context)) get_new_mmu_context(mm); diff --git a/kernel/fork.c b/kernel/fork.c index efac2c58ec7d..158710d22566 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -470,13 +470,6 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) if (clone_flags & CLONE_VM) { atomic_inc(&oldmm->mm_users); mm = oldmm; - /* - * There are cases where the PTL is held to ensure no - * new threads start up in user mode using an mm, which - * allows optimizing out ipis; the tlb_gather_mmu code - * is an example. - */ - spin_unlock_wait(&oldmm->page_table_lock); goto good_mm; } -- cgit v1.2.3 From b128254fdb172eaa3273de24fa6ce405a1f534c9 Mon Sep 17 00:00:00 2001 From: Georg Chini Date: Mon, 7 Nov 2005 14:09:19 -0800 Subject: [SPARC]: More abstractions and cleanups of dma handling in cs4231. From: Georg Chini Signed-off-by: David S. Miller --- include/asm-sparc64/ebus.h | 1 + sound/sparc/cs4231.c | 683 +++++++++++++++++++++++---------------------- 2 files changed, 343 insertions(+), 341 deletions(-) (limited to 'include') diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h index 543e4e500a72..7a408a030f52 100644 --- a/include/asm-sparc64/ebus.h +++ b/include/asm-sparc64/ebus.h @@ -79,6 +79,7 @@ extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, size_t len); extern void ebus_dma_prepare(struct ebus_dma_info *p, int write); extern unsigned int ebus_dma_residue(struct ebus_dma_info *p); +extern unsigned int ebus_dma_addr(struct ebus_dma_info *p); extern void ebus_dma_enable(struct ebus_dma_info *p, int on); extern struct linux_ebus *ebus_chain; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 110d64d4848d..1f8d27a6152e 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -62,25 +62,36 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); #ifdef SBUS_SUPPORT -struct sbus_dma_info { +typedef struct sbus_dma_info { spinlock_t lock; int dir; void __iomem *regs; -}; +} sbus_dma_info_t; #endif -typedef struct snd_cs4231 { - spinlock_t lock; - void __iomem *port; +typedef struct snd_cs4231 cs4231_t; + +typedef struct cs4231_dma_control { + void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); + void (*enable)(struct cs4231_dma_control *dma_cont, int on); + int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); + unsigned int (*address)(struct cs4231_dma_control *dma_cont); + void (*reset)(cs4231_t *chip); + void (*preallocate)(cs4231_t *chip, snd_pcm_t *pcm); #ifdef EBUS_SUPPORT - struct ebus_dma_info eb2c; - struct ebus_dma_info eb2p; + struct ebus_dma_info ebus_info; #endif - #ifdef SBUS_SUPPORT - struct sbus_dma_info sb2c; - struct sbus_dma_info sb2p; + struct sbus_dma_info sbus_info; #endif +} cs4231_dma_control_t; + +struct snd_cs4231 { + spinlock_t lock; + void __iomem *port; + + cs4231_dma_control_t p_dma; + cs4231_dma_control_t c_dma; u32 flags; #define CS4231_FLAG_EBUS 0x00000001 @@ -119,7 +130,7 @@ typedef struct snd_cs4231 { unsigned int irq[2]; unsigned int regs_size; struct snd_cs4231 *next; -} cs4231_t; +}; static cs4231_t *cs4231_list; @@ -493,103 +504,6 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) return ret; } -/* - * SBUS DMA routines - */ -#ifdef SBUS_SUPPORT - -int sbus_dma_request(struct sbus_dma_info *base, dma_addr_t bus_addr, size_t len) -{ - unsigned long flags; - u32 test, csr; - int err; - - if (len >= (1 << 24)) - return -EINVAL; - spin_lock_irqsave(&base->lock, flags); - csr = sbus_readl(base->regs + APCCSR); - err = -EINVAL; - test = APC_CDMA_READY; - if ( base->dir == APC_PLAY ) - test = APC_PDMA_READY; - if (!(csr & test)) - goto out; - err = -EBUSY; - csr = sbus_readl(base->regs + APCCSR); - test = APC_XINT_CNVA; - if ( base->dir == APC_PLAY ) - test = APC_XINT_PNVA; - if (!(csr & test)) - goto out; - err = 0; - sbus_writel(bus_addr, base->regs + base->dir + APCNVA); - sbus_writel(len, base->regs + base->dir + APCNC); -out: - spin_unlock_irqrestore(&base->lock, flags); - return err; -} - -void sbus_dma_prepare(struct sbus_dma_info *base) -{ - unsigned long flags; - u32 csr, test; - - spin_lock_irqsave(&base->lock, flags); - csr = sbus_readl(base->regs + APCCSR); - test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | - APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | - APC_XINT_PENA; - if ( base->dir == APC_RECORD ) - test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | - APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; - csr |= test; - sbus_writel(csr, base->regs + APCCSR); - spin_unlock_irqrestore(&base->lock, flags); -} - -void sbus_dma_enable(struct sbus_dma_info *base, int on) -{ - unsigned long flags; - u32 csr, shift; - - spin_lock_irqsave(&base->lock, flags); - if (!on) { - if (base->dir == APC_PLAY) { - sbus_writel(0, base->regs + base->dir + APCNVA); - sbus_writel(1, base->regs + base->dir + APCC); - } - else - { - sbus_writel(0, base->regs + base->dir + APCNC); - sbus_writel(0, base->regs + base->dir + APCVA); - } - } - udelay(500); - csr = sbus_readl(base->regs + APCCSR); - shift = 0; - if ( base->dir == APC_PLAY ) - shift = 1; - if (on) - csr &= ~(APC_CPAUSE << shift); - else - csr |= (APC_CPAUSE << shift); - sbus_writel(csr, base->regs + APCCSR); - if (on) - csr |= (APC_CDMA_READY << shift); - else - csr &= ~(APC_CDMA_READY << shift); - sbus_writel(csr, base->regs + APCCSR); - - spin_unlock_irqrestore(&base->lock, flags); -} - -unsigned int sbus_dma_addr(struct sbus_dma_info *base) -{ - return sbus_readl(base->regs + base->dir + APCVA); -} - -#endif - /* * CS4231 detection / MCE routines */ @@ -688,8 +602,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) spin_unlock_irqrestore(&chip->lock, flags); } -#ifdef EBUS_SUPPORT -static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) +static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, snd_pcm_substream_t *substream, unsigned int *periods_sent) { snd_pcm_runtime_t *runtime = substream->runtime; @@ -700,89 +613,41 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre if (period_size >= (1 << 24)) BUG(); - if (ebus_dma_request(p, runtime->dma_addr + offset, period_size)) + if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size)) return; (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; } } -#endif - -#ifdef SBUS_SUPPORT -static void snd_cs4231_sbus_advance_dma(struct sbus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - - while (1) { - unsigned int period_size = snd_pcm_lib_period_bytes(substream); - unsigned int offset = period_size * (*periods_sent); - - if (period_size > 0xffff + 1) - BUG(); - - if (sbus_dma_request(p, runtime->dma_addr + offset, period_size)) - return; - (*periods_sent) = (*periods_sent + 1) % runtime->periods; - } -} -#endif static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on) { cs4231_t *chip = snd_pcm_substream_chip(substream); + cs4231_dma_control_t *dma_cont; -#ifdef EBUS_SUPPORT - if (chip->flags & CS4231_FLAG_EBUS) { - if (what & CS4231_PLAYBACK_ENABLE) { - if (on) { - ebus_dma_prepare(&chip->eb2p, 0); - ebus_dma_enable(&chip->eb2p, 1); - snd_cs4231_ebus_advance_dma(&chip->eb2p, - chip->playback_substream, - &chip->p_periods_sent); - } else { - ebus_dma_enable(&chip->eb2p, 0); - } - } - if (what & CS4231_RECORD_ENABLE) { - if (on) { - ebus_dma_prepare(&chip->eb2c, 1); - ebus_dma_enable(&chip->eb2c, 1); - snd_cs4231_ebus_advance_dma(&chip->eb2c, - chip->capture_substream, - &chip->c_periods_sent); - } else { - ebus_dma_enable(&chip->eb2c, 0); - } - } - } else { -#endif -#ifdef SBUS_SUPPORT if (what & CS4231_PLAYBACK_ENABLE) { + dma_cont = &chip->p_dma; if (on) { - sbus_dma_prepare(&chip->sb2p); - sbus_dma_enable(&chip->sb2p, 1); - snd_cs4231_sbus_advance_dma(&chip->sb2p, + dma_cont->prepare(dma_cont, 0); + dma_cont->enable(dma_cont, 1); + snd_cs4231_advance_dma(dma_cont, chip->playback_substream, &chip->p_periods_sent); } else { - sbus_dma_enable(&chip->sb2p, 0); + dma_cont->enable(dma_cont, 0); } } if (what & CS4231_RECORD_ENABLE) { + dma_cont = &chip->c_dma; if (on) { - sbus_dma_prepare(&chip->sb2c); - sbus_dma_enable(&chip->sb2c, 1); - snd_cs4231_sbus_advance_dma(&chip->sb2c, + dma_cont->prepare(dma_cont, 1); + dma_cont->enable(dma_cont, 1); + snd_cs4231_advance_dma(dma_cont, chip->capture_substream, &chip->c_periods_sent); } else { - sbus_dma_enable(&chip->sb2c, 0); + dma_cont->enable(dma_cont, 0); } } -#endif -#ifdef EBUS_SUPPORT - } -#endif } static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) @@ -1273,140 +1138,55 @@ static void snd_cs4231_overrange(cs4231_t *chip) chip->capture_substream->runtime->overrange++; } -#ifdef SBUS_SUPPORT -static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - unsigned char status; - u32 csr; - cs4231_t *chip = dev_id; - - /*This is IRQ is not raised by the cs4231*/ - if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) - return IRQ_NONE; - - /* ACK the APC interrupt. */ - csr = sbus_readl(chip->port + APCCSR); - - sbus_writel(csr, chip->port + APCCSR); - - if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) && - (csr & APC_PLAY_INT) && - (csr & APC_XINT_PNVA) && - !(csr & APC_XINT_EMPT)) { - snd_pcm_period_elapsed(chip->playback_substream); - snd_cs4231_sbus_advance_dma(&chip->sb2p, chip->playback_substream, - &chip->p_periods_sent); - } - - if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && - (csr & APC_CAPT_INT) && - (csr & APC_XINT_CNVA) && - !(csr & APC_XINT_EMPT)) { - snd_pcm_period_elapsed(chip->capture_substream); - snd_cs4231_sbus_advance_dma(&chip->sb2c,chip->capture_substream, - &chip->c_periods_sent); - } - - status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); - - if (status & CS4231_TIMER_IRQ) { - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - } - - if (status & CS4231_RECORD_IRQ) - snd_cs4231_overrange(chip); - - /* ACK the CS4231 interrupt. */ - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} -#endif - -#ifdef EBUS_SUPPORT -static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_play_callback(cs4231_t *cookie) { cs4231_t *chip = cookie; if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) { snd_pcm_period_elapsed(chip->playback_substream); - snd_cs4231_ebus_advance_dma(p, chip->playback_substream, + snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream, &chip->p_periods_sent); } } -static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_capture_callback(cs4231_t *cookie) { cs4231_t *chip = cookie; if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) { snd_pcm_period_elapsed(chip->capture_substream); - snd_cs4231_ebus_advance_dma(p, chip->capture_substream, + snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream, &chip->c_periods_sent); } } -#endif static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); + cs4231_dma_control_t *dma_cont = &chip->p_dma; size_t ptr; -#ifdef EBUS_SUPPORT - size_t residue, period_bytes; -#endif if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) return 0; -#ifdef EBUS_SUPPORT - period_bytes = snd_pcm_lib_period_bytes(substream); - ptr = period_bytes * chip->p_periods_sent; - if (chip->flags & CS4231_FLAG_EBUS) { - residue = ebus_dma_residue(&chip->eb2p); - ptr += period_bytes - residue; - } else { -#endif -#ifdef SBUS_SUPPORT - ptr = sbus_dma_addr(&chip->sb2p); - if (ptr != 0) - ptr -= substream->runtime->dma_addr; -#endif -#ifdef EBUS_SUPPORT - } -#endif - + ptr = dma_cont->address(dma_cont); + if (ptr != 0) + ptr -= substream->runtime->dma_addr; + return bytes_to_frames(substream->runtime, ptr); } static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); + cs4231_dma_control_t *dma_cont = &chip->c_dma; size_t ptr; -#ifdef EBUS_SUPPORT - size_t residue, period_bytes; -#endif if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) return 0; -#ifdef EBUS_SUPPORT - period_bytes = snd_pcm_lib_period_bytes(substream); - ptr = period_bytes * chip->c_periods_sent; - if (chip->flags & CS4231_FLAG_EBUS) { - residue = ebus_dma_residue(&chip->eb2c); - ptr += period_bytes - residue; - } else { -#endif -#ifdef SBUS_SUPPORT - ptr = sbus_dma_addr(&chip->sb2c); - if (ptr != 0) - ptr -= substream->runtime->dma_addr; -#endif -#ifdef EBUS_SUPPORT - } -#endif + ptr = dma_cont->address(dma_cont); + if (ptr != 0) + ptr -= substream->runtime->dma_addr; + return bytes_to_frames(substream->runtime, ptr); } @@ -1442,30 +1222,8 @@ static int snd_cs4231_probe(cs4231_t *chip) spin_lock_irqsave(&chip->lock, flags); - /* Reset DMA engine. */ -#ifdef EBUS_SUPPORT - if (chip->flags & CS4231_FLAG_EBUS) { - /* Done by ebus_dma_register */ - } else { -#endif -#ifdef SBUS_SUPPORT - sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); - sbus_writel(0x00, chip->port + APCCSR); - sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, - chip->port + APCCSR); - - udelay(20); - - sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, - chip->port + APCCSR); - sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | - APC_XINT_PENA | - APC_XINT_CENA), - chip->port + APCCSR); -#endif -#ifdef EBUS_SUPPORT - } -#endif + /* Reset DMA engine (sbus only). */ + chip->p_dma.reset(chip); __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); @@ -1585,8 +1343,8 @@ static int snd_cs4231_playback_close(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - chip->playback_substream = NULL; snd_cs4231_close(chip, CS4231_MODE_PLAY); + chip->playback_substream = NULL; return 0; } @@ -1595,8 +1353,8 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - chip->capture_substream = NULL; snd_cs4231_close(chip, CS4231_MODE_RECORD); + chip->capture_substream = NULL; return 0; } @@ -1651,21 +1409,7 @@ int snd_cs4231_pcm(cs4231_t *chip) pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; strcpy(pcm->name, "CS4231"); -#ifdef EBUS_SUPPORT - if (chip->flags & CS4231_FLAG_EBUS) { - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->dev_u.pdev), - 64*1024, 128*1024); - } else { -#endif -#ifdef SBUS_SUPPORT - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, - snd_dma_sbus_data(chip->dev_u.sdev), - 64*1024, 128*1024); -#endif -#ifdef EBUS_SUPPORT - } -#endif + chip->p_dma.preallocate(chip, pcm); chip->pcm = pcm; @@ -2022,6 +1766,180 @@ out_err: } #ifdef SBUS_SUPPORT + +static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + unsigned char status; + u32 csr; + cs4231_t *chip = dev_id; + + /*This is IRQ is not raised by the cs4231*/ + if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) + return IRQ_NONE; + + /* ACK the APC interrupt. */ + csr = sbus_readl(chip->port + APCCSR); + + sbus_writel(csr, chip->port + APCCSR); + + if ((csr & APC_PDMA_READY) && + (csr & APC_PLAY_INT) && + (csr & APC_XINT_PNVA) && + !(csr & APC_XINT_EMPT)) + snd_cs4231_play_callback(chip); + + if ((csr & APC_CDMA_READY) && + (csr & APC_CAPT_INT) && + (csr & APC_XINT_CNVA) && + !(csr & APC_XINT_EMPT)) + snd_cs4231_capture_callback(chip); + + status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); + + if (status & CS4231_TIMER_IRQ) { + if (chip->timer) + snd_timer_interrupt(chip->timer, chip->timer->sticks); + } + + if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) + snd_cs4231_overrange(chip); + + /* ACK the CS4231 interrupt. */ + spin_lock_irqsave(&chip->lock, flags); + snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); + spin_unlock_irqrestore(&chip->lock, flags); + + return 0; +} + +/* + * SBUS DMA routines + */ + +int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +{ + unsigned long flags; + u32 test, csr; + int err; + sbus_dma_info_t *base = &dma_cont->sbus_info; + + if (len >= (1 << 24)) + return -EINVAL; + spin_lock_irqsave(&base->lock, flags); + csr = sbus_readl(base->regs + APCCSR); + err = -EINVAL; + test = APC_CDMA_READY; + if ( base->dir == APC_PLAY ) + test = APC_PDMA_READY; + if (!(csr & test)) + goto out; + err = -EBUSY; + csr = sbus_readl(base->regs + APCCSR); + test = APC_XINT_CNVA; + if ( base->dir == APC_PLAY ) + test = APC_XINT_PNVA; + if (!(csr & test)) + goto out; + err = 0; + sbus_writel(bus_addr, base->regs + base->dir + APCNVA); + sbus_writel(len, base->regs + base->dir + APCNC); +out: + spin_unlock_irqrestore(&base->lock, flags); + return err; +} + +void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) +{ + unsigned long flags; + u32 csr, test; + sbus_dma_info_t *base = &dma_cont->sbus_info; + + spin_lock_irqsave(&base->lock, flags); + csr = sbus_readl(base->regs + APCCSR); + test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | + APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | + APC_XINT_PENA; + if ( base->dir == APC_RECORD ) + test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | + APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; + csr |= test; + sbus_writel(csr, base->regs + APCCSR); + spin_unlock_irqrestore(&base->lock, flags); +} + +void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) +{ + unsigned long flags; + u32 csr, shift; + sbus_dma_info_t *base = &dma_cont->sbus_info; + + spin_lock_irqsave(&base->lock, flags); + if (!on) { + if (base->dir == APC_PLAY) { + sbus_writel(0, base->regs + base->dir + APCNVA); + sbus_writel(1, base->regs + base->dir + APCC); + } + else + { + sbus_writel(0, base->regs + base->dir + APCNC); + sbus_writel(0, base->regs + base->dir + APCVA); + } + } + udelay(600); + csr = sbus_readl(base->regs + APCCSR); + shift = 0; + if ( base->dir == APC_PLAY ) + shift = 1; + if (on) + csr &= ~(APC_CPAUSE << shift); + else + csr |= (APC_CPAUSE << shift); + sbus_writel(csr, base->regs + APCCSR); + if (on) + csr |= (APC_CDMA_READY << shift); + else + csr &= ~(APC_CDMA_READY << shift); + sbus_writel(csr, base->regs + APCCSR); + + spin_unlock_irqrestore(&base->lock, flags); +} + +unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) +{ + sbus_dma_info_t *base = &dma_cont->sbus_info; + + return sbus_readl(base->regs + base->dir + APCVA); +} + +void sbus_dma_reset(cs4231_t *chip) +{ + sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); + sbus_writel(0x00, chip->port + APCCSR); + sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, + chip->port + APCCSR); + + udelay(20); + + sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, + chip->port + APCCSR); + sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | + APC_XINT_PENA | + APC_XINT_CENA), + chip->port + APCCSR); +} + +void sbus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm) +{ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, + snd_dma_sbus_data(chip->dev_u.sdev), + 64*1024, 128*1024); +} + +/* + * Init and exit routines + */ + static int snd_cs4231_sbus_free(cs4231_t *chip) { if (chip->irq[0]) @@ -2063,8 +1981,8 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, return -ENOMEM; spin_lock_init(&chip->lock); - spin_lock_init(&chip->sb2c.lock); - spin_lock_init(&chip->sb2p.lock); + spin_lock_init(&chip->c_dma.sbus_info.lock); + spin_lock_init(&chip->p_dma.sbus_info.lock); init_MUTEX(&chip->mce_mutex); init_MUTEX(&chip->open_mutex); chip->card = card; @@ -2080,10 +1998,24 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, return -EIO; } - chip->sb2c.regs = chip->port; - chip->sb2p.regs = chip->port; - chip->sb2c.dir = APC_RECORD; - chip->sb2p.dir = APC_PLAY; + chip->c_dma.sbus_info.regs = chip->port; + chip->p_dma.sbus_info.regs = chip->port; + chip->c_dma.sbus_info.dir = APC_RECORD; + chip->p_dma.sbus_info.dir = APC_PLAY; + + chip->p_dma.prepare = sbus_dma_prepare; + chip->p_dma.enable = sbus_dma_enable; + chip->p_dma.request = sbus_dma_request; + chip->p_dma.address = sbus_dma_addr; + chip->p_dma.reset = sbus_dma_reset; + chip->p_dma.preallocate = sbus_dma_preallocate; + + chip->c_dma.prepare = sbus_dma_prepare; + chip->c_dma.enable = sbus_dma_enable; + chip->c_dma.request = sbus_dma_request; + chip->c_dma.address = sbus_dma_addr; + chip->c_dma.reset = sbus_dma_reset; + chip->c_dma.preallocate = sbus_dma_preallocate; if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, SA_SHIRQ, "cs4231", chip)) { @@ -2138,15 +2070,70 @@ static int cs4231_sbus_attach(struct sbus_dev *sdev) #endif #ifdef EBUS_SUPPORT + +static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) +{ + cs4231_t *chip = cookie; + + snd_cs4231_play_callback(chip); +} + +static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) +{ + cs4231_t *chip = cookie; + + snd_cs4231_capture_callback(chip); +} + +/* + * EBUS DMA wrappers + */ + +int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +{ + return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); +} + +void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on) +{ + ebus_dma_enable(&dma_cont->ebus_info, on); +} + +void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir) +{ + ebus_dma_prepare(&dma_cont->ebus_info, dir); +} + +unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) +{ + return ebus_dma_addr(&dma_cont->ebus_info); +} + +void _ebus_dma_reset(cs4231_t *chip) +{ + return; +} + +void _ebus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm) +{ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(chip->dev_u.pdev), + 64*1024, 128*1024); +} + +/* + * Init and exit routines + */ + static int snd_cs4231_ebus_free(cs4231_t *chip) { - if (chip->eb2c.regs) { - ebus_dma_unregister(&chip->eb2c); - iounmap(chip->eb2c.regs); + if (chip->c_dma.ebus_info.regs) { + ebus_dma_unregister(&chip->c_dma.ebus_info); + iounmap(chip->c_dma.ebus_info.regs); } - if (chip->eb2p.regs) { - ebus_dma_unregister(&chip->eb2p); - iounmap(chip->eb2p.regs); + if (chip->p_dma.ebus_info.regs) { + ebus_dma_unregister(&chip->p_dma.ebus_info); + iounmap(chip->p_dma.ebus_info.regs); } if (chip->port) @@ -2184,8 +2171,8 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, return -ENOMEM; spin_lock_init(&chip->lock); - spin_lock_init(&chip->eb2c.lock); - spin_lock_init(&chip->eb2p.lock); + spin_lock_init(&chip->c_dma.ebus_info.lock); + spin_lock_init(&chip->p_dma.ebus_info.lock); init_MUTEX(&chip->mce_mutex); init_MUTEX(&chip->open_mutex); chip->flags |= CS4231_FLAG_EBUS; @@ -2193,43 +2180,57 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, chip->dev_u.pdev = edev->bus->self; memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); - strcpy(chip->eb2c.name, "cs4231(capture)"); - chip->eb2c.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; - chip->eb2c.callback = snd_cs4231_ebus_capture_callback; - chip->eb2c.client_cookie = chip; - chip->eb2c.irq = edev->irqs[0]; - strcpy(chip->eb2p.name, "cs4231(play)"); - chip->eb2p.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; - chip->eb2p.callback = snd_cs4231_ebus_play_callback; - chip->eb2p.client_cookie = chip; - chip->eb2p.irq = edev->irqs[1]; + strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); + chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; + chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; + chip->c_dma.ebus_info.client_cookie = chip; + chip->c_dma.ebus_info.irq = edev->irqs[0]; + strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); + chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; + chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; + chip->p_dma.ebus_info.client_cookie = chip; + chip->p_dma.ebus_info.irq = edev->irqs[1]; + + chip->p_dma.prepare = _ebus_dma_prepare; + chip->p_dma.enable = _ebus_dma_enable; + chip->p_dma.request = _ebus_dma_request; + chip->p_dma.address = _ebus_dma_addr; + chip->p_dma.reset = _ebus_dma_reset; + chip->p_dma.preallocate = _ebus_dma_preallocate; + + chip->c_dma.prepare = _ebus_dma_prepare; + chip->c_dma.enable = _ebus_dma_enable; + chip->c_dma.request = _ebus_dma_request; + chip->c_dma.address = _ebus_dma_addr; + chip->c_dma.reset = _ebus_dma_reset; + chip->c_dma.preallocate = _ebus_dma_preallocate; chip->port = ioremap(edev->resource[0].start, 0x10); - chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10); - chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); - if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { + chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); + chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); + if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; } - if (ebus_dma_register(&chip->eb2c)) { + if (ebus_dma_register(&chip->c_dma.ebus_info)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); return -EBUSY; } - if (ebus_dma_irq_enable(&chip->eb2c, 1)) { + if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); return -EBUSY; } - if (ebus_dma_register(&chip->eb2p)) { + if (ebus_dma_register(&chip->p_dma.ebus_info)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); return -EBUSY; } - if (ebus_dma_irq_enable(&chip->eb2p, 1)) { + if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); return -EBUSY; -- cgit v1.2.3 From 62dbec78be652c28f63ad5eda3d01c244c916040 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2005 14:09:58 -0800 Subject: [SPARC64] mm: Do not flush TLB mm in tlb_finish_mmu() It isn't needed any longer, as noted by Hugh Dickins. We still need the flush routines, due to the one remaining call site in hugetlb_prefault_arch_hook(). That can be eliminated at some later point, however. Signed-off-by: David S. Miller --- arch/sparc64/kernel/smp.c | 48 +++++++++++++++++------------------------------ include/asm-sparc64/tlb.h | 6 ++---- 2 files changed, 19 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index a9089e2140e9..5d90ee9aebf1 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -839,43 +839,29 @@ void smp_flush_tlb_all(void) * questionable (in theory the big win for threads is the massive sharing of * address space state across processors). */ + +/* This currently is only used by the hugetlb arch pre-fault + * hook on UltraSPARC-III+ and later when changing the pagesize + * bits of the context register for an address space. + */ void smp_flush_tlb_mm(struct mm_struct *mm) { - /* - * This code is called from two places, dup_mmap and exit_mmap. In the - * former case, we really need a flush. In the later case, the callers - * are single threaded exec_mmap (really need a flush), multithreaded - * exec_mmap case (do not need to flush, since the caller gets a new - * context via activate_mm), and all other callers of mmput() whence - * the flush can be optimized since the associated threads are dead and - * the mm is being torn down (__exit_mm and other mmput callers) or the - * owning thread is dissociating itself from the mm. The - * (atomic_read(&mm->mm_users) == 0) check ensures real work is done - * for single thread exec and dup_mmap cases. An alternate check might - * have been (current->mm != mm). - * Kanoj Sarcar - */ - if (atomic_read(&mm->mm_users) == 0) - return; - - { - u32 ctx = CTX_HWBITS(mm->context); - int cpu = get_cpu(); + u32 ctx = CTX_HWBITS(mm->context); + int cpu = get_cpu(); - if (atomic_read(&mm->mm_users) == 1) { - mm->cpu_vm_mask = cpumask_of_cpu(cpu); - goto local_flush_and_out; - } + if (atomic_read(&mm->mm_users) == 1) { + mm->cpu_vm_mask = cpumask_of_cpu(cpu); + goto local_flush_and_out; + } - smp_cross_call_masked(&xcall_flush_tlb_mm, - ctx, 0, 0, - mm->cpu_vm_mask); + smp_cross_call_masked(&xcall_flush_tlb_mm, + ctx, 0, 0, + mm->cpu_vm_mask); - local_flush_and_out: - __flush_tlb_mm(ctx, SECONDARY_CONTEXT); +local_flush_and_out: + __flush_tlb_mm(ctx, SECONDARY_CONTEXT); - put_cpu(); - } + put_cpu(); } void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs) diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h index 66138d959df5..1eda17954f39 100644 --- a/include/asm-sparc64/tlb.h +++ b/include/asm-sparc64/tlb.h @@ -78,11 +78,9 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un { tlb_flush_mmu(mp); - if (mp->fullmm) { - if (CTX_VALID(mp->mm->context)) - do_flush_tlb_mm(mp->mm); + if (mp->fullmm) mp->fullmm = 0; - } else + else flush_tlb_pending(); /* keep the page table cache within bounds */ -- cgit v1.2.3 From d16436e686949a17b3bcfff2d688c97354b599aa Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 7 Nov 2005 14:10:42 -0800 Subject: [SPARC]: remove duplicate TIOCPKT_ definitions The TIOCPKT_ macros are defined by all other architectures in asm/ioctls.h and so does sparc and sparc64, so reomve the duplicates in asm/termios.h. Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- include/asm-sparc/termios.h | 9 --------- include/asm-sparc64/termios.h | 9 --------- 2 files changed, 18 deletions(-) (limited to 'include') diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index 0a8ad4cac125..d05f83c80989 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -38,15 +38,6 @@ struct sunos_ttysize { int st_columns; /* Columns on the terminal */ }; -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - struct winsize { unsigned short ws_row; unsigned short ws_col; diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index 9777a9cca88a..ee26a071c677 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -38,15 +38,6 @@ struct sunos_ttysize { int st_columns; /* Columns on the terminal */ }; -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - struct winsize { unsigned short ws_row; unsigned short ws_col; -- cgit v1.2.3 From 9d3c7d1bfd41d5082a541666db404aae7699b79e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:14 -0800 Subject: [SPARC]: remove audioio.h The old sound drivers are gone in 2.6, so the only user left are the compat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 7 -- include/asm-sparc/audioio.h | 234 ------------------------------------------ include/asm-sparc64/audioio.h | 234 ------------------------------------------ 3 files changed, 475 deletions(-) delete mode 100644 include/asm-sparc/audioio.h delete mode 100644 include/asm-sparc64/audioio.h (limited to 'include') diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 0e587d6de319..6fda044a7372 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -19,7 +19,6 @@ #include #include #include -#include #include /* Use this to get at 32-bit user passed pointers. @@ -524,12 +523,6 @@ COMPATIBLE_IOCTL(OPROMPATH2NODE) COMPATIBLE_IOCTL(LOOP_SET_STATUS64) COMPATIBLE_IOCTL(LOOP_GET_STATUS64) /* Big A */ -COMPATIBLE_IOCTL(AUDIO_GETINFO) -COMPATIBLE_IOCTL(AUDIO_SETINFO) -COMPATIBLE_IOCTL(AUDIO_DRAIN) -COMPATIBLE_IOCTL(AUDIO_GETDEV) -COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS) -COMPATIBLE_IOCTL(AUDIO_FLUSH) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) diff --git a/include/asm-sparc/audioio.h b/include/asm-sparc/audioio.h deleted file mode 100644 index cf16173f521b..000000000000 --- a/include/asm-sparc/audioio.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * include/asm-sparc/audioio.h - * - * Sparc Audio Midlayer - * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - */ - -#ifndef _AUDIOIO_H_ -#define _AUDIOIO_H_ - -/* - * SunOS/Solaris /dev/audio interface - */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) -#include -#include -#include -#endif - -/* - * This structure contains state information for audio device IO streams. - */ -typedef struct audio_prinfo { - /* - * The following values describe the audio data encoding. - */ - unsigned int sample_rate; /* samples per second */ - unsigned int channels; /* number of interleaved channels */ - unsigned int precision; /* bit-width of each sample */ - unsigned int encoding; /* data encoding method */ - - /* - * The following values control audio device configuration - */ - unsigned int gain; /* gain level: 0 - 255 */ - unsigned int port; /* selected I/O port (see below) */ - unsigned int avail_ports; /* available I/O ports (see below) */ - unsigned int _xxx[2]; /* Reserved for future use */ - - unsigned int buffer_size; /* I/O buffer size */ - - /* - * The following values describe driver state - */ - unsigned int samples; /* number of samples converted */ - unsigned int eof; /* End Of File counter (play only) */ - - unsigned char pause; /* non-zero for pause, zero to resume */ - unsigned char error; /* non-zero if overflow/underflow */ - unsigned char waiting; /* non-zero if a process wants access */ - unsigned char balance; /* stereo channel balance */ - - unsigned short minordev; - - /* - * The following values are read-only state flags - */ - unsigned char open; /* non-zero if open access permitted */ - unsigned char active; /* non-zero if I/O is active */ -} audio_prinfo_t; - - -/* - * This structure describes the current state of the audio device. - */ -typedef struct audio_info { - /* - * Per-stream information - */ - audio_prinfo_t play; /* output status information */ - audio_prinfo_t record; /* input status information */ - - /* - * Per-unit/channel information - */ - unsigned int monitor_gain; /* input to output mix: 0 - 255 */ - unsigned char output_muted; /* non-zero if output is muted */ - unsigned char _xxx[3]; /* Reserved for future use */ - unsigned int _yyy[3]; /* Reserved for future use */ -} audio_info_t; - - -/* - * Audio encoding types - */ -#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ -#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ -#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ -#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ -#define AUDIO_ENCODING_FLOAT (4) /* IEEE float (-1. <-> +1.) */ -#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ -#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ -#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ - -/* - * These ranges apply to record, play, and monitor gain values - */ -#define AUDIO_MIN_GAIN (0) /* minimum gain value */ -#define AUDIO_MAX_GAIN (255) /* maximum gain value */ - -/* - * These values apply to the balance field to adjust channel gain values - */ -#define AUDIO_LEFT_BALANCE (0) /* left channel only */ -#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ -#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ -#define AUDIO_BALANCE_SHIFT (3) - -/* - * Generic minimum/maximum limits for number of channels, both modes - */ -#define AUDIO_MIN_PLAY_CHANNELS (1) -#define AUDIO_MAX_PLAY_CHANNELS (4) -#define AUDIO_MIN_REC_CHANNELS (1) -#define AUDIO_MAX_REC_CHANNELS (4) - -/* - * Generic minimum/maximum limits for sample precision - */ -#define AUDIO_MIN_PLAY_PRECISION (8) -#define AUDIO_MAX_PLAY_PRECISION (32) -#define AUDIO_MIN_REC_PRECISION (8) -#define AUDIO_MAX_REC_PRECISION (32) - -/* - * Define some convenient names for typical audio ports - */ -/* - * output ports (several may be enabled simultaneously) - */ -#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ -#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ -#define AUDIO_LINE_OUT 0x04 /* output to line out */ - -/* - * input ports (usually only one at a time) - */ -#define AUDIO_MICROPHONE 0x01 /* input from microphone */ -#define AUDIO_LINE_IN 0x02 /* input from line in */ -#define AUDIO_CD 0x04 /* input from on-board CD inputs */ -#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ -#define AUDIO_ANALOG_LOOPBACK 0x40 /* input from output */ - - -/* - * This macro initializes an audio_info structure to 'harmless' values. - * Note that (~0) might not be a harmless value for a flag that was - * a signed int. - */ -#define AUDIO_INITINFO(i) { \ - unsigned int *__x__; \ - for (__x__ = (unsigned int *)(i); \ - (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ - *__x__++ = ~0); \ -} - -/* - * These allow testing for what the user wants to set - */ -#define AUD_INITVALUE (~0) -#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) -#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) -#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) - -/* - * Parameter for the AUDIO_GETDEV ioctl to determine current - * audio devices. - */ -#define MAX_AUDIO_DEV_LEN (16) -typedef struct audio_device { - char name[MAX_AUDIO_DEV_LEN]; - char version[MAX_AUDIO_DEV_LEN]; - char config[MAX_AUDIO_DEV_LEN]; -} audio_device_t; - - -/* - * Ioctl calls for the audio device. - */ - -/* - * AUDIO_GETINFO retrieves the current state of the audio device. - * - * AUDIO_SETINFO copies all fields of the audio_info structure whose - * values are not set to the initialized value (-1) to the device state. - * It performs an implicit AUDIO_GETINFO to return the new state of the - * device. Note that the record.samples and play.samples fields are set - * to the last value before the AUDIO_SETINFO took effect. This allows - * an application to reset the counters while atomically retrieving the - * last value. - * - * AUDIO_DRAIN suspends the calling process until the write buffers are - * empty. - * - * AUDIO_GETDEV returns a structure of type audio_device_t which contains - * three strings. The string "name" is a short identifying string (for - * example, the SBus Fcode name string), the string "version" identifies - * the current version of the device, and the "config" string identifies - * the specific configuration of the audio stream. All fields are - * device-dependent -- see the device specific manual pages for details. - * - * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined - * herein (making it not too portable) - * - * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, - * resets error counters, and restarts recording and playback as appropriate - * for the current sampling mode. - */ -#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) -#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) -#define AUDIO_DRAIN _IO('A', 3) -#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) -#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) -#define AUDIO_FLUSH _IO('A', 5) - -/* Define possible audio hardware configurations for - * old SunOS-style AUDIO_GETDEV ioctl */ -#define AUDIO_DEV_UNKNOWN (0) /* not defined */ -#define AUDIO_DEV_AMD (1) /* audioamd device */ -#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ -#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ -#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ - -/* - * The following ioctl sets the audio device into an internal loopback mode, - * if the hardware supports this. The argument is TRUE to set loopback, - * FALSE to reset to normal operation. If the hardware does not support - * internal loopback, the ioctl should fail with EINVAL. - * Causes ADC data to be digitally mixed in and sent to the DAC. - */ -#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) - -#endif /* _AUDIOIO_H_ */ diff --git a/include/asm-sparc64/audioio.h b/include/asm-sparc64/audioio.h deleted file mode 100644 index cf16173f521b..000000000000 --- a/include/asm-sparc64/audioio.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * include/asm-sparc/audioio.h - * - * Sparc Audio Midlayer - * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - */ - -#ifndef _AUDIOIO_H_ -#define _AUDIOIO_H_ - -/* - * SunOS/Solaris /dev/audio interface - */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) -#include -#include -#include -#endif - -/* - * This structure contains state information for audio device IO streams. - */ -typedef struct audio_prinfo { - /* - * The following values describe the audio data encoding. - */ - unsigned int sample_rate; /* samples per second */ - unsigned int channels; /* number of interleaved channels */ - unsigned int precision; /* bit-width of each sample */ - unsigned int encoding; /* data encoding method */ - - /* - * The following values control audio device configuration - */ - unsigned int gain; /* gain level: 0 - 255 */ - unsigned int port; /* selected I/O port (see below) */ - unsigned int avail_ports; /* available I/O ports (see below) */ - unsigned int _xxx[2]; /* Reserved for future use */ - - unsigned int buffer_size; /* I/O buffer size */ - - /* - * The following values describe driver state - */ - unsigned int samples; /* number of samples converted */ - unsigned int eof; /* End Of File counter (play only) */ - - unsigned char pause; /* non-zero for pause, zero to resume */ - unsigned char error; /* non-zero if overflow/underflow */ - unsigned char waiting; /* non-zero if a process wants access */ - unsigned char balance; /* stereo channel balance */ - - unsigned short minordev; - - /* - * The following values are read-only state flags - */ - unsigned char open; /* non-zero if open access permitted */ - unsigned char active; /* non-zero if I/O is active */ -} audio_prinfo_t; - - -/* - * This structure describes the current state of the audio device. - */ -typedef struct audio_info { - /* - * Per-stream information - */ - audio_prinfo_t play; /* output status information */ - audio_prinfo_t record; /* input status information */ - - /* - * Per-unit/channel information - */ - unsigned int monitor_gain; /* input to output mix: 0 - 255 */ - unsigned char output_muted; /* non-zero if output is muted */ - unsigned char _xxx[3]; /* Reserved for future use */ - unsigned int _yyy[3]; /* Reserved for future use */ -} audio_info_t; - - -/* - * Audio encoding types - */ -#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ -#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ -#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ -#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ -#define AUDIO_ENCODING_FLOAT (4) /* IEEE float (-1. <-> +1.) */ -#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ -#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ -#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ - -/* - * These ranges apply to record, play, and monitor gain values - */ -#define AUDIO_MIN_GAIN (0) /* minimum gain value */ -#define AUDIO_MAX_GAIN (255) /* maximum gain value */ - -/* - * These values apply to the balance field to adjust channel gain values - */ -#define AUDIO_LEFT_BALANCE (0) /* left channel only */ -#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ -#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ -#define AUDIO_BALANCE_SHIFT (3) - -/* - * Generic minimum/maximum limits for number of channels, both modes - */ -#define AUDIO_MIN_PLAY_CHANNELS (1) -#define AUDIO_MAX_PLAY_CHANNELS (4) -#define AUDIO_MIN_REC_CHANNELS (1) -#define AUDIO_MAX_REC_CHANNELS (4) - -/* - * Generic minimum/maximum limits for sample precision - */ -#define AUDIO_MIN_PLAY_PRECISION (8) -#define AUDIO_MAX_PLAY_PRECISION (32) -#define AUDIO_MIN_REC_PRECISION (8) -#define AUDIO_MAX_REC_PRECISION (32) - -/* - * Define some convenient names for typical audio ports - */ -/* - * output ports (several may be enabled simultaneously) - */ -#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ -#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ -#define AUDIO_LINE_OUT 0x04 /* output to line out */ - -/* - * input ports (usually only one at a time) - */ -#define AUDIO_MICROPHONE 0x01 /* input from microphone */ -#define AUDIO_LINE_IN 0x02 /* input from line in */ -#define AUDIO_CD 0x04 /* input from on-board CD inputs */ -#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ -#define AUDIO_ANALOG_LOOPBACK 0x40 /* input from output */ - - -/* - * This macro initializes an audio_info structure to 'harmless' values. - * Note that (~0) might not be a harmless value for a flag that was - * a signed int. - */ -#define AUDIO_INITINFO(i) { \ - unsigned int *__x__; \ - for (__x__ = (unsigned int *)(i); \ - (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ - *__x__++ = ~0); \ -} - -/* - * These allow testing for what the user wants to set - */ -#define AUD_INITVALUE (~0) -#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) -#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) -#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) - -/* - * Parameter for the AUDIO_GETDEV ioctl to determine current - * audio devices. - */ -#define MAX_AUDIO_DEV_LEN (16) -typedef struct audio_device { - char name[MAX_AUDIO_DEV_LEN]; - char version[MAX_AUDIO_DEV_LEN]; - char config[MAX_AUDIO_DEV_LEN]; -} audio_device_t; - - -/* - * Ioctl calls for the audio device. - */ - -/* - * AUDIO_GETINFO retrieves the current state of the audio device. - * - * AUDIO_SETINFO copies all fields of the audio_info structure whose - * values are not set to the initialized value (-1) to the device state. - * It performs an implicit AUDIO_GETINFO to return the new state of the - * device. Note that the record.samples and play.samples fields are set - * to the last value before the AUDIO_SETINFO took effect. This allows - * an application to reset the counters while atomically retrieving the - * last value. - * - * AUDIO_DRAIN suspends the calling process until the write buffers are - * empty. - * - * AUDIO_GETDEV returns a structure of type audio_device_t which contains - * three strings. The string "name" is a short identifying string (for - * example, the SBus Fcode name string), the string "version" identifies - * the current version of the device, and the "config" string identifies - * the specific configuration of the audio stream. All fields are - * device-dependent -- see the device specific manual pages for details. - * - * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined - * herein (making it not too portable) - * - * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, - * resets error counters, and restarts recording and playback as appropriate - * for the current sampling mode. - */ -#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) -#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) -#define AUDIO_DRAIN _IO('A', 3) -#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) -#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) -#define AUDIO_FLUSH _IO('A', 5) - -/* Define possible audio hardware configurations for - * old SunOS-style AUDIO_GETDEV ioctl */ -#define AUDIO_DEV_UNKNOWN (0) /* not defined */ -#define AUDIO_DEV_AMD (1) /* audioamd device */ -#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ -#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ -#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ - -/* - * The following ioctl sets the audio device into an internal loopback mode, - * if the hardware supports this. The argument is TRUE to set loopback, - * FALSE to reset to normal operation. If the hardware does not support - * internal loopback, the ioctl should fail with EINVAL. - * Causes ADC data to be digitally mixed in and sent to the DAC. - */ -#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) - -#endif /* _AUDIOIO_H_ */ -- cgit v1.2.3 From e1413315b8dfcdebc61416dadc1334619dfb4543 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:25 -0800 Subject: [SPARC]: remove kbio.h The old keyboard driver is gone in 2.6, so the only user left are the compat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 11 --------- include/asm-sparc/kbio.h | 56 ------------------------------------------- include/asm-sparc64/kbio.h | 56 ------------------------------------------- 3 files changed, 123 deletions(-) delete mode 100644 include/asm-sparc/kbio.h delete mode 100644 include/asm-sparc64/kbio.h (limited to 'include') diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 6fda044a7372..947bd265aaa4 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -473,16 +472,6 @@ COMPATIBLE_IOCTL(FBIOSCURPOS) COMPATIBLE_IOCTL(FBIOGCURPOS) COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little k */ -COMPATIBLE_IOCTL(KIOCTYPE) -COMPATIBLE_IOCTL(KIOCLAYOUT) -COMPATIBLE_IOCTL(KIOCGTRANS) -COMPATIBLE_IOCTL(KIOCTRANS) -COMPATIBLE_IOCTL(KIOCCMD) -COMPATIBLE_IOCTL(KIOCSDIRECT) -COMPATIBLE_IOCTL(KIOCSLED) -COMPATIBLE_IOCTL(KIOCGLED) -COMPATIBLE_IOCTL(KIOCSRATE) -COMPATIBLE_IOCTL(KIOCGRATE) COMPATIBLE_IOCTL(VUIDSFORMAT) COMPATIBLE_IOCTL(VUIDGFORMAT) /* Little v, the video4linux ioctls */ diff --git a/include/asm-sparc/kbio.h b/include/asm-sparc/kbio.h deleted file mode 100644 index 3cf496bdf399..000000000000 --- a/include/asm-sparc/kbio.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __LINUX_KBIO_H -#define __LINUX_KBIO_H - -/* Return keyboard type */ -#define KIOCTYPE _IOR('k', 9, int) -/* Return Keyboard layout */ -#define KIOCLAYOUT _IOR('k', 20, int) - -enum { - TR_NONE, - TR_ASCII, /* keyboard is in regular state */ - TR_EVENT, /* keystrokes sent as firm events */ - TR_UNTRANS_EVENT /* EVENT+up and down+no translation */ -}; - -/* Return the current keyboard translation */ -#define KIOCGTRANS _IOR('k', 5, int) -/* Set the keyboard translation */ -#define KIOCTRANS _IOW('k', 0, int) - -/* Send a keyboard command */ -#define KIOCCMD _IOW('k', 8, int) - -/* Return if keystrokes are being sent to /dev/kbd */ - -/* Set routing of keystrokes to /dev/kbd */ -#define KIOCSDIRECT _IOW('k', 10, int) - -/* Set keyboard leds */ -#define KIOCSLED _IOW('k', 14, unsigned char) - -/* Get keyboard leds */ -#define KIOCGLED _IOR('k', 15, unsigned char) - -/* Used by KIOC[GS]RATE */ -struct kbd_rate { - unsigned char delay; /* Delay in Hz before first repeat. */ - unsigned char rate; /* In characters per second (0..50). */ -}; - -/* Set keyboard rate */ -#define KIOCSRATE _IOW('k', 40, struct kbd_rate) - -/* Get keyboard rate */ -#define KIOCGRATE _IOW('k', 41, struct kbd_rate) - -/* Top bit records if the key is up or down */ -#define KBD_UP 0x80 - -/* Usable information */ -#define KBD_KEYMASK 0x7f - -/* All keys up */ -#define KBD_IDLE 0x75 - -#endif /* __LINUX_KBIO_H */ diff --git a/include/asm-sparc64/kbio.h b/include/asm-sparc64/kbio.h deleted file mode 100644 index 3cf496bdf399..000000000000 --- a/include/asm-sparc64/kbio.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __LINUX_KBIO_H -#define __LINUX_KBIO_H - -/* Return keyboard type */ -#define KIOCTYPE _IOR('k', 9, int) -/* Return Keyboard layout */ -#define KIOCLAYOUT _IOR('k', 20, int) - -enum { - TR_NONE, - TR_ASCII, /* keyboard is in regular state */ - TR_EVENT, /* keystrokes sent as firm events */ - TR_UNTRANS_EVENT /* EVENT+up and down+no translation */ -}; - -/* Return the current keyboard translation */ -#define KIOCGTRANS _IOR('k', 5, int) -/* Set the keyboard translation */ -#define KIOCTRANS _IOW('k', 0, int) - -/* Send a keyboard command */ -#define KIOCCMD _IOW('k', 8, int) - -/* Return if keystrokes are being sent to /dev/kbd */ - -/* Set routing of keystrokes to /dev/kbd */ -#define KIOCSDIRECT _IOW('k', 10, int) - -/* Set keyboard leds */ -#define KIOCSLED _IOW('k', 14, unsigned char) - -/* Get keyboard leds */ -#define KIOCGLED _IOR('k', 15, unsigned char) - -/* Used by KIOC[GS]RATE */ -struct kbd_rate { - unsigned char delay; /* Delay in Hz before first repeat. */ - unsigned char rate; /* In characters per second (0..50). */ -}; - -/* Set keyboard rate */ -#define KIOCSRATE _IOW('k', 40, struct kbd_rate) - -/* Get keyboard rate */ -#define KIOCGRATE _IOW('k', 41, struct kbd_rate) - -/* Top bit records if the key is up or down */ -#define KBD_UP 0x80 - -/* Usable information */ -#define KBD_KEYMASK 0x7f - -/* All keys up */ -#define KBD_IDLE 0x75 - -#endif /* __LINUX_KBIO_H */ -- cgit v1.2.3 From 59f85dc95e81281b424b2eb0e7b002cf7f77db03 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:38 -0800 Subject: [SPARC]: remove vuid_event.h I don't know if we ever implemented this, but the only user in any 2.6 tree are the compat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 3 --- include/asm-m68k/vuid_event.h | 4 ---- include/asm-sparc/vuid_event.h | 41 ---------------------------------------- include/asm-sparc64/vuid_event.h | 40 --------------------------------------- 4 files changed, 88 deletions(-) delete mode 100644 include/asm-m68k/vuid_event.h delete mode 100644 include/asm-sparc/vuid_event.h delete mode 100644 include/asm-sparc64/vuid_event.h (limited to 'include') diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 947bd265aaa4..94e2b99802c8 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -472,8 +471,6 @@ COMPATIBLE_IOCTL(FBIOSCURPOS) COMPATIBLE_IOCTL(FBIOGCURPOS) COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little k */ -COMPATIBLE_IOCTL(VUIDSFORMAT) -COMPATIBLE_IOCTL(VUIDGFORMAT) /* Little v, the video4linux ioctls */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ diff --git a/include/asm-m68k/vuid_event.h b/include/asm-m68k/vuid_event.h deleted file mode 100644 index 52ecb521a395..000000000000 --- a/include/asm-m68k/vuid_event.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _M68K_VUID_EVENT_H -#define _M68K_VUID_EVENT_H -#include -#endif diff --git a/include/asm-sparc/vuid_event.h b/include/asm-sparc/vuid_event.h deleted file mode 100644 index 7781e9f2fdd3..000000000000 --- a/include/asm-sparc/vuid_event.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SunOS Virtual User Input Device (VUID) compatibility */ - - -typedef struct firm_event { - unsigned short id; /* tag for this event */ - unsigned char pair_type; /* unused by X11 */ - unsigned char pair; /* unused by X11 */ - int value; /* VKEY_UP, VKEY_DOWN or delta */ - struct timeval time; -} Firm_event; - -enum { - FE_PAIR_NONE, - FE_PAIR_SET, - FE_PAIR_DELTA, - FE_PAIR_ABSOLUTE -}; - -/* VUID stream formats */ -#define VUID_NATIVE 0 /* Native byte stream format */ -#define VUID_FIRM_EVENT 1 /* send firm_event structures */ - -/* ioctls */ - /* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */ -#define VUIDSFORMAT _IOW('v', 1, int) - /* Retrieve input device byte stream format */ -#define VUIDGFORMAT _IOR('v', 2, int) - -/* Possible tag values */ -/* mouse buttons: */ -#define MS_LEFT 0x7f20 -#define MS_MIDDLE 0x7f21 -#define MS_RIGHT 0x7f22 -/* motion: */ -#define LOC_X_DELTA 0x7f80 -#define LOC_Y_DELTA 0x7f81 -#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */ -#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */ - -#define VKEY_UP 0 -#define VKEY_DOWN 1 diff --git a/include/asm-sparc64/vuid_event.h b/include/asm-sparc64/vuid_event.h deleted file mode 100644 index 9ef4d17ad08f..000000000000 --- a/include/asm-sparc64/vuid_event.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SunOS Virtual User Input Device (VUID) compatibility */ - -typedef struct firm_event { - unsigned short id; /* tag for this event */ - unsigned char pair_type; /* unused by X11 */ - unsigned char pair; /* unused by X11 */ - int value; /* VKEY_UP, VKEY_DOWN or delta */ - struct timeval time; -} Firm_event; - -enum { - FE_PAIR_NONE, - FE_PAIR_SET, - FE_PAIR_DELTA, - FE_PAIR_ABSOLUTE -}; - -/* VUID stream formats */ -#define VUID_NATIVE 0 /* Native byte stream format */ -#define VUID_FIRM_EVENT 1 /* send firm_event structures */ - -/* ioctls */ - /* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */ -#define VUIDSFORMAT _IOW('v', 1, int) - /* Retrieve input device byte stream format */ -#define VUIDGFORMAT _IOR('v', 2, int) - -/* Possible tag values */ -/* mouse buttons: */ -#define MS_LEFT 0x7f20 -#define MS_MIDDLE 0x7f21 -#define MS_RIGHT 0x7f22 -/* motion: */ -#define LOC_X_DELTA 0x7f80 -#define LOC_Y_DELTA 0x7f81 -#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */ -#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */ - -#define VKEY_UP 0 -#define VKEY_DOWN 1 -- cgit v1.2.3 From 59871bcd1197014aacdf8e398c407cab70ab74e7 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 7 Nov 2005 14:12:08 -0800 Subject: [SPARC64] mm: simpler tlb_flush_mmu Minor simplification to the sparc64 tlb_flush_mmu: tlb_remove_page set need_flush only after handling the tlb_fast_mode case, then tlb_flush_mmu need not consider whether it's tlb_fast_mode. Signed-off-by: Hugh Dickins Signed-off-by: David S. Miller --- include/asm-sparc64/tlb.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h index 1eda17954f39..61c01882b562 100644 --- a/include/asm-sparc64/tlb.h +++ b/include/asm-sparc64/tlb.h @@ -58,11 +58,9 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned i static inline void tlb_flush_mmu(struct mmu_gather *mp) { if (mp->need_flush) { + free_pages_and_swap_cache(mp->pages, mp->pages_nr); + mp->pages_nr = 0; mp->need_flush = 0; - if (!tlb_fast_mode(mp)) { - free_pages_and_swap_cache(mp->pages, mp->pages_nr); - mp->pages_nr = 0; - } } } @@ -91,11 +89,11 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page) { - mp->need_flush = 1; if (tlb_fast_mode(mp)) { free_page_and_swap_cache(page); return; } + mp->need_flush = 1; mp->pages[mp->pages_nr++] = page; if (mp->pages_nr >= FREE_PTE_NR) tlb_flush_mmu(mp); -- cgit v1.2.3 From 16cf0d816541fde06ed8f37c0f5cf9940cdfc145 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:12:21 -0800 Subject: [SPARC]: Kill remaining kbio.h references. Would you mind applying the following patch that kills those two + the m68k and Documentation/ references? Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- Documentation/ioctl-number.txt | 2 -- arch/sparc/kernel/sunos_ioctl.c | 1 - arch/sparc64/kernel/sunos_ioctl32.c | 1 - include/asm-m68k/kbio.h | 1 - 4 files changed, 5 deletions(-) delete mode 100644 include/asm-m68k/kbio.h (limited to 'include') diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index 769f925c8526..87f4d052e39c 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -130,8 +130,6 @@ Code Seq# Include File Comments 'i' 00-3F linux/i2o.h 'j' 00-3F linux/joystick.h -'k' all asm-sparc/kbio.h - asm-sparc64/kbio.h 'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system 'l' 40-7F linux/udf_fs_i.h in development: diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c index df1c0b31a930..a6ba3d26222c 100644 --- a/arch/sparc/kernel/sunos_ioctl.c +++ b/arch/sparc/kernel/sunos_ioctl.c @@ -23,7 +23,6 @@ #include #include #include -#include #if 0 extern char sunkbd_type; diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c index 7654b8a7f03a..3f619ead22cc 100644 --- a/arch/sparc64/kernel/sunos_ioctl32.c +++ b/arch/sparc64/kernel/sunos_ioctl32.c @@ -24,7 +24,6 @@ #include #include #include -#include #define SUNOS_NR_OPEN 256 diff --git a/include/asm-m68k/kbio.h b/include/asm-m68k/kbio.h deleted file mode 100644 index e1fbf8fba3e8..000000000000 --- a/include/asm-m68k/kbio.h +++ /dev/null @@ -1 +0,0 @@ -#include -- cgit v1.2.3 From d7e02edbc52bc689279154b117b90fe6635fc14b Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 24 Oct 2005 20:44:06 -0500 Subject: Update version ieee80211 stamp to 1.1.7 --- include/net/ieee80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 5e38dca1d082..b93fd8c1d884 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -29,7 +29,7 @@ #include /* ARRAY_SIZE */ #include -#define IEEE80211_VERSION "git-1.1.6" +#define IEEE80211_VERSION "git-1.1.7" #define IEEE80211_DATA_LEN 2304 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section -- cgit v1.2.3 From 4350147a816b9c5b40fa59e4fa23f17490630b79 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:27:33 +1100 Subject: [PATCH] ppc64: SMU based macs cpufreq support CPU freq support using 970FX powertune facility for iMac G5 and SMU based single CPU desktop. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 8 + arch/powerpc/kernel/misc_64.S | 70 +++ arch/powerpc/platforms/powermac/Makefile | 3 +- arch/powerpc/platforms/powermac/cpufreq.c | 726 -------------------------- arch/powerpc/platforms/powermac/cpufreq_32.c | 727 +++++++++++++++++++++++++++ arch/powerpc/platforms/powermac/cpufreq_64.c | 323 ++++++++++++ arch/powerpc/platforms/powermac/setup.c | 13 - arch/ppc64/Kconfig | 10 + arch/ppc64/kernel/misc.S | 72 ++- drivers/macintosh/smu.c | 12 + include/asm-powerpc/reg.h | 9 +- include/asm-powerpc/smu.h | 60 ++- 12 files changed, 1290 insertions(+), 743 deletions(-) delete mode 100644 arch/powerpc/platforms/powermac/cpufreq.c create mode 100644 arch/powerpc/platforms/powermac/cpufreq_32.c create mode 100644 arch/powerpc/platforms/powermac/cpufreq_64.c (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6ffae2d2b3fa..3ac9195dab35 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -404,6 +404,14 @@ config CPU_FREQ_PMAC this currently includes some models of iBook & Titanium PowerBook. +config CPU_FREQ_PMAC64 + bool "Support for some Apple G5s" + depends on CPU_FREQ && PMAC_SMU && PPC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple iMac G5, + and some of the more recent desktop G5 machines as well. + config PPC601_SYNC_FIX bool "Workarounds for PPC601 bugs" depends on 6xx && (PPC_PREP || PPC_PMAC) diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index b3e95ff0dba0..ae1433da09b2 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -603,6 +603,76 @@ _GLOBAL(real_writeb) blr #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ +/* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + ori r0,r4,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + isync + mfspr r0,SPRN_SCOMC + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + ori r0,r5,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd. + */ + + rlwinm r3,r3,8,0,15 + + sync + mtspr SPRN_SCOMD,r4 /* write data */ + isync + mtspr SPRN_SCOMC,r3 /* write command */ + isync + mfspr 3,SPRN_SCOMC + isync + + /* restore interrupts */ + mtmsrd r5,1 + blr + + /* * Create a kernel thread * kernel_thread(fn, arg, flags) diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 4369676f1d54..c9df44fcf571 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile @@ -1,7 +1,8 @@ obj-y += pic.o setup.o time.o feature.o pci.o \ sleep.o low_i2c.o cache.o obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o -obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq.o +obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o +obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o obj-$(CONFIG_NVRAM) += nvram.o # ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff obj-$(CONFIG_PPC64) += nvram.o diff --git a/arch/powerpc/platforms/powermac/cpufreq.c b/arch/powerpc/platforms/powermac/cpufreq.c deleted file mode 100644 index c47f8b69725c..000000000000 --- a/arch/powerpc/platforms/powermac/cpufreq.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * arch/ppc/platforms/pmac_cpufreq.c - * - * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt - * Copyright (C) 2004 John Steele Scott - * - * 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. - * - * TODO: Need a big cleanup here. Basically, we need to have different - * cpufreq_driver structures for the different type of HW instead of the - * current mess. We also need to better deal with the detection of the - * type of machine. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* WARNING !!! This will cause calibrate_delay() to be called, - * but this is an __init function ! So you MUST go edit - * init/main.c to make it non-init before enabling DEBUG_FREQ - */ -#undef DEBUG_FREQ - -/* - * There is a problem with the core cpufreq code on SMP kernels, - * it won't recalculate the Bogomips properly - */ -#ifdef CONFIG_SMP -#warning "WARNING, CPUFREQ not recommended on SMP kernels" -#endif - -extern void low_choose_7447a_dfs(int dfs); -extern void low_choose_750fx_pll(int pll); -extern void low_sleep_handler(void); - -/* - * Currently, PowerMac cpufreq supports only high & low frequencies - * that are set by the firmware - */ -static unsigned int low_freq; -static unsigned int hi_freq; -static unsigned int cur_freq; -static unsigned int sleep_freq; - -/* - * Different models uses different mecanisms to switch the frequency - */ -static int (*set_speed_proc)(int low_speed); -static unsigned int (*get_speed_proc)(void); - -/* - * Some definitions used by the various speedprocs - */ -static u32 voltage_gpio; -static u32 frequency_gpio; -static u32 slew_done_gpio; -static int no_schedule; -static int has_cpu_l2lve; -static int is_pmu_based; - -/* There are only two frequency states for each processor. Values - * are in kHz for the time being. - */ -#define CPUFREQ_HIGH 0 -#define CPUFREQ_LOW 1 - -static struct cpufreq_frequency_table pmac_cpu_freqs[] = { - {CPUFREQ_HIGH, 0}, - {CPUFREQ_LOW, 0}, - {0, CPUFREQ_TABLE_END}, -}; - -static struct freq_attr* pmac_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - -static inline void local_delay(unsigned long ms) -{ - if (no_schedule) - mdelay(ms); - else - msleep(ms); -} - -#ifdef DEBUG_FREQ -static inline void debug_calc_bogomips(void) -{ - /* This will cause a recalc of bogomips and display the - * result. We backup/restore the value to avoid affecting the - * core cpufreq framework's own calculation. - */ - extern void calibrate_delay(void); - - unsigned long save_lpj = loops_per_jiffy; - calibrate_delay(); - loops_per_jiffy = save_lpj; -} -#endif /* DEBUG_FREQ */ - -/* Switch CPU speed under 750FX CPU control - */ -static int cpu_750fx_cpu_speed(int low_speed) -{ - u32 hid2; - - if (low_speed == 0) { - /* ramping up, set voltage first */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Make sure we sleep for at least 1ms */ - local_delay(10); - - /* tweak L2 for high voltage */ - if (has_cpu_l2lve) { - hid2 = mfspr(SPRN_HID2); - hid2 &= ~0x2000; - mtspr(SPRN_HID2, hid2); - } - } -#ifdef CONFIG_6xx - low_choose_750fx_pll(low_speed); -#endif - if (low_speed == 1) { - /* tweak L2 for low voltage */ - if (has_cpu_l2lve) { - hid2 = mfspr(SPRN_HID2); - hid2 |= 0x2000; - mtspr(SPRN_HID2, hid2); - } - - /* ramping down, set voltage last */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - local_delay(10); - } - - return 0; -} - -static unsigned int cpu_750fx_get_cpu_speed(void) -{ - if (mfspr(SPRN_HID1) & HID1_PS) - return low_freq; - else - return hi_freq; -} - -/* Switch CPU speed using DFS */ -static int dfs_set_cpu_speed(int low_speed) -{ - if (low_speed == 0) { - /* ramping up, set voltage first */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Make sure we sleep for at least 1ms */ - local_delay(1); - } - - /* set frequency */ -#ifdef CONFIG_6xx - low_choose_7447a_dfs(low_speed); -#endif - udelay(100); - - if (low_speed == 1) { - /* ramping down, set voltage last */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - local_delay(1); - } - - return 0; -} - -static unsigned int dfs_get_cpu_speed(void) -{ - if (mfspr(SPRN_HID1) & HID1_DFS) - return low_freq; - else - return hi_freq; -} - - -/* Switch CPU speed using slewing GPIOs - */ -static int gpios_set_cpu_speed(int low_speed) -{ - int gpio, timeout = 0; - - /* If ramping up, set voltage first */ - if (low_speed == 0) { - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Delay is way too big but it's ok, we schedule */ - local_delay(10); - } - - /* Set frequency */ - gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - if (low_speed == ((gpio & 0x01) == 0)) - goto skip; - - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, - low_speed ? 0x04 : 0x05); - udelay(200); - do { - if (++timeout > 100) - break; - local_delay(1); - gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); - } while((gpio & 0x02) == 0); - skip: - /* If ramping down, set voltage last */ - if (low_speed == 1) { - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - /* Delay is way too big but it's ok, we schedule */ - local_delay(10); - } - -#ifdef DEBUG_FREQ - debug_calc_bogomips(); -#endif - - return 0; -} - -/* Switch CPU speed under PMU control - */ -static int pmu_set_cpu_speed(int low_speed) -{ - struct adb_request req; - unsigned long save_l2cr; - unsigned long save_l3cr; - unsigned int pic_prio; - unsigned long flags; - - preempt_disable(); - -#ifdef DEBUG_FREQ - printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); -#endif - pmu_suspend(); - - /* Disable all interrupt sources on openpic */ - pic_prio = mpic_cpu_get_priority(); - mpic_cpu_set_priority(0xf); - - /* Make sure the decrementer won't interrupt us */ - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - /* Make sure any pending DEC interrupt occuring while we did - * the above didn't re-enable the DEC */ - mb(); - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - - /* We can now disable MSR_EE */ - local_irq_save(flags); - - /* Giveup the FPU & vec */ - enable_kernel_fp(); - -#ifdef CONFIG_ALTIVEC - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - enable_kernel_altivec(); -#endif /* CONFIG_ALTIVEC */ - - /* Save & disable L2 and L3 caches */ - save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ - save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ - - /* Send the new speed command. My assumption is that this command - * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep - */ - pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); - while (!req.complete) - pmu_poll(); - - /* Prepare the northbridge for the speed transition */ - pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); - - /* Call low level code to backup CPU state and recover from - * hardware reset - */ - low_sleep_handler(); - - /* Restore the northbridge */ - pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); - - /* Restore L2 cache */ - if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) - _set_L2CR(save_l2cr); - /* Restore L3 cache */ - if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) - _set_L3CR(save_l3cr); - - /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); - -#ifdef DEBUG_FREQ - printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); -#endif - - /* Restore low level PMU operations */ - pmu_unlock(); - - /* Restore decrementer */ - wakeup_decrementer(); - - /* Restore interrupts */ - mpic_cpu_set_priority(pic_prio); - - /* Let interrupts flow again ... */ - local_irq_restore(flags); - -#ifdef DEBUG_FREQ - debug_calc_bogomips(); -#endif - - pmu_resume(); - - preempt_enable(); - - return 0; -} - -static int do_set_cpu_speed(int speed_mode, int notify) -{ - struct cpufreq_freqs freqs; - unsigned long l3cr; - static unsigned long prev_l3cr; - - freqs.old = cur_freq; - freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - freqs.cpu = smp_processor_id(); - - if (freqs.old == freqs.new) - return 0; - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (speed_mode == CPUFREQ_LOW && - cpu_has_feature(CPU_FTR_L3CR)) { - l3cr = _get_L3CR(); - if (l3cr & L3CR_L3E) { - prev_l3cr = l3cr; - _set_L3CR(0); - } - } - set_speed_proc(speed_mode == CPUFREQ_LOW); - if (speed_mode == CPUFREQ_HIGH && - cpu_has_feature(CPU_FTR_L3CR)) { - l3cr = _get_L3CR(); - if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) - _set_L3CR(prev_l3cr); - } - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - - return 0; -} - -static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) -{ - return cur_freq; -} - -static int pmac_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); -} - -static int pmac_cpufreq_target( struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, - target_freq, relation, &newstate)) - return -EINVAL; - - return do_set_cpu_speed(newstate, 1); -} - -unsigned int pmac_get_one_cpufreq(int i) -{ - /* Supports only one CPU for now */ - return (i == 0) ? cur_freq : 0; -} - -static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -ENODEV; - - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = cur_freq; - - cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); -} - -static u32 read_gpio(struct device_node *np) -{ - u32 *reg = (u32 *)get_property(np, "reg", NULL); - u32 offset; - - if (reg == NULL) - return 0; - /* That works for all keylargos but shall be fixed properly - * some day... The problem is that it seems we can't rely - * on the "reg" property of the GPIO nodes, they are either - * relative to the base of KeyLargo or to the base of the - * GPIO space, and the device-tree doesn't help. - */ - offset = *reg; - if (offset < KEYLARGO_GPIO_LEVELS0) - offset += KEYLARGO_GPIO_LEVELS0; - return offset; -} - -static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) -{ - /* Ok, this could be made a bit smarter, but let's be robust for now. We - * always force a speed change to high speed before sleep, to make sure - * we have appropriate voltage and/or bus speed for the wakeup process, - * and to make sure our loops_per_jiffies are "good enough", that is will - * not cause too short delays if we sleep in low speed and wake in high - * speed.. - */ - no_schedule = 1; - sleep_freq = cur_freq; - if (cur_freq == low_freq && !is_pmu_based) - do_set_cpu_speed(CPUFREQ_HIGH, 0); - return 0; -} - -static int pmac_cpufreq_resume(struct cpufreq_policy *policy) -{ - /* If we resume, first check if we have a get() function */ - if (get_speed_proc) - cur_freq = get_speed_proc(); - else - cur_freq = 0; - - /* We don't, hrm... we don't really know our speed here, best - * is that we force a switch to whatever it was, which is - * probably high speed due to our suspend() routine - */ - do_set_cpu_speed(sleep_freq == low_freq ? - CPUFREQ_LOW : CPUFREQ_HIGH, 0); - - no_schedule = 0; - return 0; -} - -static struct cpufreq_driver pmac_cpufreq_driver = { - .verify = pmac_cpufreq_verify, - .target = pmac_cpufreq_target, - .get = pmac_cpufreq_get_speed, - .init = pmac_cpufreq_cpu_init, - .suspend = pmac_cpufreq_suspend, - .resume = pmac_cpufreq_resume, - .flags = CPUFREQ_PM_NO_WARN, - .attr = pmac_cpu_freqs_attr, - .name = "powermac", - .owner = THIS_MODULE, -}; - - -static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np = of_find_node_by_name(NULL, - "voltage-gpio"); - struct device_node *freq_gpio_np = of_find_node_by_name(NULL, - "frequency-gpio"); - struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, - "slewing-done"); - u32 *value; - - /* - * Check to see if it's GPIO driven or PMU only - * - * The way we extract the GPIO address is slightly hackish, but it - * works well enough for now. We need to abstract the whole GPIO - * stuff sooner or later anyway - */ - - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (freq_gpio_np) - frequency_gpio = read_gpio(freq_gpio_np); - if (slew_done_gpio_np) - slew_done_gpio = read_gpio(slew_done_gpio_np); - - /* If we use the frequency GPIOs, calculate the min/max speeds based - * on the bus frequencies - */ - if (frequency_gpio && slew_done_gpio) { - int lenp, rc; - u32 *freqs, *ratio; - - freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); - lenp /= sizeof(u32); - if (freqs == NULL || lenp != 2) { - printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); - return 1; - } - ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); - if (ratio == NULL) { - printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); - return 1; - } - - /* Get the min/max bus frequencies */ - low_freq = min(freqs[0], freqs[1]); - hi_freq = max(freqs[0], freqs[1]); - - /* Grrrr.. It _seems_ that the device-tree is lying on the low bus - * frequency, it claims it to be around 84Mhz on some models while - * it appears to be approx. 101Mhz on all. Let's hack around here... - * fortunately, we don't need to be too precise - */ - if (low_freq < 98000000) - low_freq = 101000000; - - /* Convert those to CPU core clocks */ - low_freq = (low_freq * (*ratio)) / 2000; - hi_freq = (hi_freq * (*ratio)) / 2000; - - /* Now we get the frequencies, we read the GPIO to see what is out current - * speed - */ - rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - cur_freq = (rc & 0x01) ? hi_freq : low_freq; - - set_speed_proc = gpios_set_cpu_speed; - return 1; - } - - /* If we use the PMU, look for the min & max frequencies in the - * device-tree - */ - value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); - if (!value) - return 1; - low_freq = (*value) / 1000; - /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree - * here */ - if (low_freq < 100000) - low_freq *= 10; - - value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); - if (!value) - return 1; - hi_freq = (*value) / 1000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - - return 0; -} - -static int pmac_cpufreq_init_7447A(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np; - - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) - return 1; - - volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (!voltage_gpio){ - printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); - return 1; - } - - /* OF only reports the high frequency */ - hi_freq = cur_freq; - low_freq = cur_freq/2; - - /* Read actual frequency from CPU */ - cur_freq = dfs_get_cpu_speed(); - set_speed_proc = dfs_set_cpu_speed; - get_speed_proc = dfs_get_cpu_speed; - - return 0; -} - -static int pmac_cpufreq_init_750FX(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np; - u32 pvr, *value; - - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) - return 1; - - hi_freq = cur_freq; - value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); - if (!value) - return 1; - low_freq = (*value) / 1000; - - volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - - pvr = mfspr(SPRN_PVR); - has_cpu_l2lve = !((pvr & 0xf00) == 0x100); - - set_speed_proc = cpu_750fx_cpu_speed; - get_speed_proc = cpu_750fx_get_cpu_speed; - cur_freq = cpu_750fx_get_cpu_speed(); - - return 0; -} - -/* Currently, we support the following machines: - * - * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) - * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) - * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) - * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) - * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) - * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) - * - Recent MacRISC3 laptops - * - All new machines with 7447A CPUs - */ -static int __init pmac_cpufreq_setup(void) -{ - struct device_node *cpunode; - u32 *value; - - if (strstr(cmd_line, "nocpufreq")) - return 0; - - /* Assume only one CPU */ - cpunode = find_type_devices("cpu"); - if (!cpunode) - goto out; - - /* Get current cpu clock freq */ - value = (u32 *)get_property(cpunode, "clock-frequency", NULL); - if (!value) - goto out; - cur_freq = (*value) / 1000; - - /* Check for 7447A based MacRISC3 */ - if (machine_is_compatible("MacRISC3") && - get_property(cpunode, "dynamic-power-step", NULL) && - PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { - pmac_cpufreq_init_7447A(cpunode); - /* Check for other MacRISC3 machines */ - } else if (machine_is_compatible("PowerBook3,4") || - machine_is_compatible("PowerBook3,5") || - machine_is_compatible("MacRISC3")) { - pmac_cpufreq_init_MacRISC3(cpunode); - /* Else check for iBook2 500/600 */ - } else if (machine_is_compatible("PowerBook4,1")) { - hi_freq = cur_freq; - low_freq = 400000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for TiPb 550 */ - else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { - hi_freq = cur_freq; - low_freq = 500000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for TiPb 400 & 500 */ - else if (machine_is_compatible("PowerBook3,2")) { - /* We only know about the 400 MHz and the 500Mhz model - * they both have 300 MHz as low frequency - */ - if (cur_freq < 350000 || cur_freq > 550000) - goto out; - hi_freq = cur_freq; - low_freq = 300000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for 750FX */ - else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) - pmac_cpufreq_init_750FX(cpunode); -out: - if (set_speed_proc == NULL) - return -ENODEV; - - pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; - pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; - - printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", - low_freq/1000, hi_freq/1000, cur_freq/1000); - - return cpufreq_register_driver(&pmac_cpufreq_driver); -} - -module_init(pmac_cpufreq_setup); - diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c new file mode 100644 index 000000000000..7960a7bfca0a --- /dev/null +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -0,0 +1,727 @@ +/* + * arch/ppc/platforms/pmac_cpufreq.c + * + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * Copyright (C) 2004 John Steele Scott + * + * 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. + * + * TODO: Need a big cleanup here. Basically, we need to have different + * cpufreq_driver structures for the different type of HW instead of the + * current mess. We also need to better deal with the detection of the + * type of machine. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* WARNING !!! This will cause calibrate_delay() to be called, + * but this is an __init function ! So you MUST go edit + * init/main.c to make it non-init before enabling DEBUG_FREQ + */ +#undef DEBUG_FREQ + +/* + * There is a problem with the core cpufreq code on SMP kernels, + * it won't recalculate the Bogomips properly + */ +#ifdef CONFIG_SMP +#warning "WARNING, CPUFREQ not recommended on SMP kernels" +#endif + +extern void low_choose_7447a_dfs(int dfs); +extern void low_choose_750fx_pll(int pll); +extern void low_sleep_handler(void); + +/* + * Currently, PowerMac cpufreq supports only high & low frequencies + * that are set by the firmware + */ +static unsigned int low_freq; +static unsigned int hi_freq; +static unsigned int cur_freq; +static unsigned int sleep_freq; + +/* + * Different models uses different mecanisms to switch the frequency + */ +static int (*set_speed_proc)(int low_speed); +static unsigned int (*get_speed_proc)(void); + +/* + * Some definitions used by the various speedprocs + */ +static u32 voltage_gpio; +static u32 frequency_gpio; +static u32 slew_done_gpio; +static int no_schedule; +static int has_cpu_l2lve; +static int is_pmu_based; + +/* There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table pmac_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* pmac_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static inline void local_delay(unsigned long ms) +{ + if (no_schedule) + mdelay(ms); + else + msleep(ms); +} + +#ifdef DEBUG_FREQ +static inline void debug_calc_bogomips(void) +{ + /* This will cause a recalc of bogomips and display the + * result. We backup/restore the value to avoid affecting the + * core cpufreq framework's own calculation. + */ + extern void calibrate_delay(void); + + unsigned long save_lpj = loops_per_jiffy; + calibrate_delay(); + loops_per_jiffy = save_lpj; +} +#endif /* DEBUG_FREQ */ + +/* Switch CPU speed under 750FX CPU control + */ +static int cpu_750fx_cpu_speed(int low_speed) +{ + u32 hid2; + + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Make sure we sleep for at least 1ms */ + local_delay(10); + + /* tweak L2 for high voltage */ + if (has_cpu_l2lve) { + hid2 = mfspr(SPRN_HID2); + hid2 &= ~0x2000; + mtspr(SPRN_HID2, hid2); + } + } +#ifdef CONFIG_6xx + low_choose_750fx_pll(low_speed); +#endif + if (low_speed == 1) { + /* tweak L2 for low voltage */ + if (has_cpu_l2lve) { + hid2 = mfspr(SPRN_HID2); + hid2 |= 0x2000; + mtspr(SPRN_HID2, hid2); + } + + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + local_delay(10); + } + + return 0; +} + +static unsigned int cpu_750fx_get_cpu_speed(void) +{ + if (mfspr(SPRN_HID1) & HID1_PS) + return low_freq; + else + return hi_freq; +} + +/* Switch CPU speed using DFS */ +static int dfs_set_cpu_speed(int low_speed) +{ + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Make sure we sleep for at least 1ms */ + local_delay(1); + } + + /* set frequency */ +#ifdef CONFIG_6xx + low_choose_7447a_dfs(low_speed); +#endif + udelay(100); + + if (low_speed == 1) { + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + local_delay(1); + } + + return 0; +} + +static unsigned int dfs_get_cpu_speed(void) +{ + if (mfspr(SPRN_HID1) & HID1_DFS) + return low_freq; + else + return hi_freq; +} + + +/* Switch CPU speed using slewing GPIOs + */ +static int gpios_set_cpu_speed(int low_speed) +{ + int gpio, timeout = 0; + + /* If ramping up, set voltage first */ + if (low_speed == 0) { + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Delay is way too big but it's ok, we schedule */ + local_delay(10); + } + + /* Set frequency */ + gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + if (low_speed == ((gpio & 0x01) == 0)) + goto skip; + + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, + low_speed ? 0x04 : 0x05); + udelay(200); + do { + if (++timeout > 100) + break; + local_delay(1); + gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); + } while((gpio & 0x02) == 0); + skip: + /* If ramping down, set voltage last */ + if (low_speed == 1) { + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + /* Delay is way too big but it's ok, we schedule */ + local_delay(10); + } + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + return 0; +} + +/* Switch CPU speed under PMU control + */ +static int pmu_set_cpu_speed(int low_speed) +{ + struct adb_request req; + unsigned long save_l2cr; + unsigned long save_l3cr; + unsigned int pic_prio; + unsigned long flags; + + preempt_disable(); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + pmu_suspend(); + + /* Disable all interrupt sources on openpic */ + pic_prio = mpic_cpu_get_priority(); + mpic_cpu_set_priority(0xf); + + /* Make sure the decrementer won't interrupt us */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + + /* We can now disable MSR_EE */ + local_irq_save(flags); + + /* Giveup the FPU & vec */ + enable_kernel_fp(); + +#ifdef CONFIG_ALTIVEC + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + /* Save & disable L2 and L3 caches */ + save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ + save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ + + /* Send the new speed command. My assumption is that this command + * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep + */ + pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); + while (!req.complete) + pmu_poll(); + + /* Prepare the northbridge for the speed transition */ + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); + + /* Call low level code to backup CPU state and recover from + * hardware reset + */ + low_sleep_handler(); + + /* Restore the northbridge */ + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); + + /* Restore L2 cache */ + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr); + /* Restore L3 cache */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); +#endif + + /* Restore low level PMU operations */ + pmu_unlock(); + + /* Restore decrementer */ + wakeup_decrementer(); + + /* Restore interrupts */ + mpic_cpu_set_priority(pic_prio); + + /* Let interrupts flow again ... */ + local_irq_restore(flags); + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + pmu_resume(); + + preempt_enable(); + + return 0; +} + +static int do_set_cpu_speed(int speed_mode, int notify) +{ + struct cpufreq_freqs freqs; + unsigned long l3cr; + static unsigned long prev_l3cr; + + freqs.old = cur_freq; + freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; + freqs.cpu = smp_processor_id(); + + if (freqs.old == freqs.new) + return 0; + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (speed_mode == CPUFREQ_LOW && + cpu_has_feature(CPU_FTR_L3CR)) { + l3cr = _get_L3CR(); + if (l3cr & L3CR_L3E) { + prev_l3cr = l3cr; + _set_L3CR(0); + } + } + set_speed_proc(speed_mode == CPUFREQ_LOW); + if (speed_mode == CPUFREQ_HIGH && + cpu_has_feature(CPU_FTR_L3CR)) { + l3cr = _get_L3CR(); + if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) + _set_L3CR(prev_l3cr); + } + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; + + return 0; +} + +static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) +{ + return cur_freq; +} + +static int pmac_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); +} + +static int pmac_cpufreq_target( struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + int rc; + + if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + rc = do_set_cpu_speed(newstate, 1); + + ppc_proc_freq = cur_freq * 1000ul; + return rc; +} + +static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = cur_freq; + + cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); + return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); +} + +static u32 read_gpio(struct device_node *np) +{ + u32 *reg = (u32 *)get_property(np, "reg", NULL); + u32 offset; + + if (reg == NULL) + return 0; + /* That works for all keylargos but shall be fixed properly + * some day... The problem is that it seems we can't rely + * on the "reg" property of the GPIO nodes, they are either + * relative to the base of KeyLargo or to the base of the + * GPIO space, and the device-tree doesn't help. + */ + offset = *reg; + if (offset < KEYLARGO_GPIO_LEVELS0) + offset += KEYLARGO_GPIO_LEVELS0; + return offset; +} + +static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) +{ + /* Ok, this could be made a bit smarter, but let's be robust for now. We + * always force a speed change to high speed before sleep, to make sure + * we have appropriate voltage and/or bus speed for the wakeup process, + * and to make sure our loops_per_jiffies are "good enough", that is will + * not cause too short delays if we sleep in low speed and wake in high + * speed.. + */ + no_schedule = 1; + sleep_freq = cur_freq; + if (cur_freq == low_freq && !is_pmu_based) + do_set_cpu_speed(CPUFREQ_HIGH, 0); + return 0; +} + +static int pmac_cpufreq_resume(struct cpufreq_policy *policy) +{ + /* If we resume, first check if we have a get() function */ + if (get_speed_proc) + cur_freq = get_speed_proc(); + else) + cur_freq = 0; + + /* We don't, hrm... we don't really know our speed here, best + * is that we force a switch to whatever it was, which is + * probably high speed due to our suspend() routine + */ + do_set_cpu_speed(sleep_freq == low_freq ? + CPUFREQ_LOW : CPUFREQ_HIGH, 0); + + ppc_proc_freq = cur_freq * 1000ul; + + no_schedule = 0; + return 0; +} + +static struct cpufreq_driver pmac_cpufreq_driver = { + .verify = pmac_cpufreq_verify, + .target = pmac_cpufreq_target, + .get = pmac_cpufreq_get_speed, + .init = pmac_cpufreq_cpu_init, + .suspend = pmac_cpufreq_suspend, + .resume = pmac_cpufreq_resume, + .flags = CPUFREQ_PM_NO_WARN, + .attr = pmac_cpu_freqs_attr, + .name = "powermac", + .owner = THIS_MODULE, +}; + + +static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np = of_find_node_by_name(NULL, + "voltage-gpio"); + struct device_node *freq_gpio_np = of_find_node_by_name(NULL, + "frequency-gpio"); + struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, + "slewing-done"); + u32 *value; + + /* + * Check to see if it's GPIO driven or PMU only + * + * The way we extract the GPIO address is slightly hackish, but it + * works well enough for now. We need to abstract the whole GPIO + * stuff sooner or later anyway + */ + + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (freq_gpio_np) + frequency_gpio = read_gpio(freq_gpio_np); + if (slew_done_gpio_np) + slew_done_gpio = read_gpio(slew_done_gpio_np); + + /* If we use the frequency GPIOs, calculate the min/max speeds based + * on the bus frequencies + */ + if (frequency_gpio && slew_done_gpio) { + int lenp, rc; + u32 *freqs, *ratio; + + freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); + lenp /= sizeof(u32); + if (freqs == NULL || lenp != 2) { + printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); + return 1; + } + ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); + if (ratio == NULL) { + printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); + return 1; + } + + /* Get the min/max bus frequencies */ + low_freq = min(freqs[0], freqs[1]); + hi_freq = max(freqs[0], freqs[1]); + + /* Grrrr.. It _seems_ that the device-tree is lying on the low bus + * frequency, it claims it to be around 84Mhz on some models while + * it appears to be approx. 101Mhz on all. Let's hack around here... + * fortunately, we don't need to be too precise + */ + if (low_freq < 98000000) + low_freq = 101000000; + + /* Convert those to CPU core clocks */ + low_freq = (low_freq * (*ratio)) / 2000; + hi_freq = (hi_freq * (*ratio)) / 2000; + + /* Now we get the frequencies, we read the GPIO to see what is out current + * speed + */ + rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + cur_freq = (rc & 0x01) ? hi_freq : low_freq; + + set_speed_proc = gpios_set_cpu_speed; + return 1; + } + + /* If we use the PMU, look for the min & max frequencies in the + * device-tree + */ + value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree + * here */ + if (low_freq < 100000) + low_freq *= 10; + + value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); + if (!value) + return 1; + hi_freq = (*value) / 1000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + + return 0; +} + +static int pmac_cpufreq_init_7447A(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + return 1; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (!voltage_gpio){ + printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); + return 1; + } + + /* OF only reports the high frequency */ + hi_freq = cur_freq; + low_freq = cur_freq/2; + + /* Read actual frequency from CPU */ + cur_freq = dfs_get_cpu_speed(); + set_speed_proc = dfs_set_cpu_speed; + get_speed_proc = dfs_get_cpu_speed; + + return 0; +} + +static int pmac_cpufreq_init_750FX(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + u32 pvr, *value; + + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + return 1; + + hi_freq = cur_freq; + value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + + pvr = mfspr(SPRN_PVR); + has_cpu_l2lve = !((pvr & 0xf00) == 0x100); + + set_speed_proc = cpu_750fx_cpu_speed; + get_speed_proc = cpu_750fx_get_cpu_speed; + cur_freq = cpu_750fx_get_cpu_speed(); + + return 0; +} + +/* Currently, we support the following machines: + * + * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) + * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) + * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) + * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) + * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) + * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) + * - Recent MacRISC3 laptops + * - All new machines with 7447A CPUs + */ +static int __init pmac_cpufreq_setup(void) +{ + struct device_node *cpunode; + u32 *value; + + if (strstr(cmd_line, "nocpufreq")) + return 0; + + /* Assume only one CPU */ + cpunode = find_type_devices("cpu"); + if (!cpunode) + goto out; + + /* Get current cpu clock freq */ + value = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!value) + goto out; + cur_freq = (*value) / 1000; + + /* Check for 7447A based MacRISC3 */ + if (machine_is_compatible("MacRISC3") && + get_property(cpunode, "dynamic-power-step", NULL) && + PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { + pmac_cpufreq_init_7447A(cpunode); + /* Check for other MacRISC3 machines */ + } else if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5") || + machine_is_compatible("MacRISC3")) { + pmac_cpufreq_init_MacRISC3(cpunode); + /* Else check for iBook2 500/600 */ + } else if (machine_is_compatible("PowerBook4,1")) { + hi_freq = cur_freq; + low_freq = 400000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for TiPb 550 */ + else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { + hi_freq = cur_freq; + low_freq = 500000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for TiPb 400 & 500 */ + else if (machine_is_compatible("PowerBook3,2")) { + /* We only know about the 400 MHz and the 500Mhz model + * they both have 300 MHz as low frequency + */ + if (cur_freq < 350000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 300000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for 750FX */ + else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) + pmac_cpufreq_init_750FX(cpunode); +out: + if (set_speed_proc == NULL) + return -ENODEV; + + pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; + pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; + ppc_proc_freq = cur_freq * 1000ul; + + printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", + low_freq/1000, hi_freq/1000, cur_freq/1000); + + return cpufreq_register_driver(&pmac_cpufreq_driver); +} + +module_init(pmac_cpufreq_setup); + diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c new file mode 100644 index 000000000000..39150342c6f1 --- /dev/null +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * and Markus Demleitner + * + * 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. + * + * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs, + * that is iMac G5 and latest single CPU desktop. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* see 970FX user manual */ + +#define SCOM_PCR 0x0aa001 /* PCR scom addr */ + +#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ +#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ +#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ +#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ +#define PCR_SPEED_MASK 0x000e0000U /* speed mask */ +#define PCR_SPEED_SHIFT 17 +#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ +#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ +#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ +#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ +#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ +#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ + +#define SCOM_PSR 0x408001 /* PSR scom addr */ +/* warning: PSR is a 64 bits register */ +#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */ +#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */ +#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */ +#define PSR_CUR_SPEED_SHIFT (56) + +/* + * The G5 only supports two frequencies (Quarter speed is not supported) + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table g5_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* g5_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* Power mode data is an array of the 32 bits PCR values to use for + * the various frequencies, retreived from the device-tree + */ +static u32 *g5_pmode_data; +static int g5_pmode_max; +static int g5_pmode_cur; + +static DECLARE_MUTEX(g5_switch_mutex); + + +static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ +static int g5_fvt_count; /* number of op. points */ +static int g5_fvt_cur; /* current op. point */ + +/* ----------------- real hardware interface */ + +static void g5_switch_volt(int speed_mode) +{ + struct smu_simple_cmd cmd; + + DECLARE_COMPLETION(comp); + smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete, + &comp, 'V', 'S', 'L', 'E', 'W', + 0xff, g5_fvt_cur+1, speed_mode); + wait_for_completion(&comp); +} + +static int g5_switch_freq(int speed_mode) +{ + struct cpufreq_freqs freqs; + int to; + + if (g5_pmode_cur == speed_mode) + return 0; + + down(&g5_switch_mutex); + + freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; + freqs.new = g5_cpu_freqs[speed_mode].frequency; + freqs.cpu = 0; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* If frequency is going up, first ramp up the voltage */ + if (speed_mode < g5_pmode_cur) + g5_switch_volt(speed_mode); + + /* Clear PCR high */ + scom970_write(SCOM_PCR, 0); + /* Clear PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); + /* Set PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | + g5_pmode_data[speed_mode]); + + /* Wait for completion */ + for (to = 0; to < 10; to++) { + unsigned long psr = scom970_read(SCOM_PSR); + + if ((psr & PSR_CMD_RECEIVED) == 0 && + (((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3) + == 0) + break; + if (psr & PSR_CMD_COMPLETED) + break; + udelay(100); + } + + /* If frequency is going down, last ramp the voltage */ + if (speed_mode > g5_pmode_cur) + g5_switch_volt(speed_mode); + + g5_pmode_cur = speed_mode; + ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul; + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + up(&g5_switch_mutex); + + return 0; +} + +static int g5_query_freq(void) +{ + unsigned long psr = scom970_read(SCOM_PSR); + int i; + + for (i = 0; i <= g5_pmode_max; i++) + if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) + break; + return i; +} + +/* ----------------- cpufreq bookkeeping */ + +static int g5_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); +} + +static int g5_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return g5_switch_freq(newstate); +} + +static unsigned int g5_cpufreq_get_speed(unsigned int cpu) +{ + return g5_cpu_freqs[g5_pmode_cur].frequency; +} + +static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; + cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, + g5_cpu_freqs); +} + + +static struct cpufreq_driver g5_cpufreq_driver = { + .name = "powermac", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = g5_cpufreq_cpu_init, + .verify = g5_cpufreq_verify, + .target = g5_cpufreq_target, + .get = g5_cpufreq_get_speed, + .attr = g5_cpu_freqs_attr, +}; + + +static int __init g5_cpufreq_init(void) +{ + struct device_node *cpunode; + unsigned int psize, ssize; + struct smu_sdbp_header *shdr; + unsigned long max_freq; + u32 *valp; + int rc = -ENODEV; + + /* Look for CPU and SMU nodes */ + cpunode = of_find_node_by_type(NULL, "cpu"); + if (!cpunode) { + DBG("No CPU node !\n"); + return -ENODEV; + } + + /* Check 970FX for now */ + valp = (u32 *)get_property(cpunode, "cpu-version", NULL); + if (!valp) { + DBG("No cpu-version property !\n"); + goto bail_noprops; + } + if (((*valp) >> 16) != 0x3c) { + DBG("Wrong CPU version: %08x\n", *valp); + goto bail_noprops; + } + + /* Look for the powertune data in the device-tree */ + g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize); + if (!g5_pmode_data) { + DBG("No power-mode-data !\n"); + goto bail_noprops; + } + g5_pmode_max = psize / sizeof(u32) - 1; + + /* Look for the FVT table */ + shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (!shdr) + goto bail_noprops; + g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; + ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header); + g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + g5_fvt_cur = 0; + + /* Sanity checking */ + if (g5_fvt_count < 1 || g5_pmode_max < 1) + goto bail_noprops; + + /* + * From what I see, clock-frequency is always the maximal frequency. + * The current driver can not slew sysclk yet, so we really only deal + * with powertune steps for now. We also only implement full freq and + * half freq in this version. So far, I haven't yet seen a machine + * supporting anything else. + */ + valp = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!valp) + return -ENODEV; + max_freq = (*valp)/1000; + g5_cpu_freqs[0].frequency = max_freq; + g5_cpu_freqs[1].frequency = max_freq/2; + + /* Check current frequency */ + g5_pmode_cur = g5_query_freq(); + if (g5_pmode_cur > 1) + /* We don't support anything but 1:1 and 1:2, fixup ... */ + g5_pmode_cur = 1; + + /* Force apply current frequency to make sure everything is in + * sync (voltage is right for example). Firmware may leave us with + * a strange setting ... + */ + g5_switch_freq(g5_pmode_cur); + + printk(KERN_INFO "Registering G5 CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + g5_cpu_freqs[1].frequency/1000, + g5_cpu_freqs[0].frequency/1000, + g5_cpu_freqs[g5_pmode_cur].frequency/1000); + + rc = cpufreq_register_driver(&g5_cpufreq_driver); + + /* We keep the CPU node on hold... hopefully, Apple G5 don't have + * hotplug CPU with a dynamic device-tree ... + */ + return rc; + + bail_noprops: + of_node_put(cpunode); + + return rc; +} + +module_init(g5_cpufreq_init); + + +MODULE_LICENSE("GPL"); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 80b58c1ec412..7acb0546671f 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -193,18 +193,6 @@ static void pmac_show_cpuinfo(struct seq_file *m) pmac_newworld ? "NewWorld" : "OldWorld"); } -static void pmac_show_percpuinfo(struct seq_file *m, int i) -{ -#ifdef CONFIG_CPU_FREQ_PMAC - extern unsigned int pmac_get_one_cpufreq(int i); - unsigned int freq = pmac_get_one_cpufreq(i); - if (freq != 0) { - seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); - return; - } -#endif /* CONFIG_CPU_FREQ_PMAC */ -} - #ifndef CONFIG_ADB_CUDA int find_via_cuda(void) { @@ -767,7 +755,6 @@ struct machdep_calls __initdata pmac_md = { .setup_arch = pmac_setup_arch, .init_early = pmac_init_early, .show_cpuinfo = pmac_show_cpuinfo, - .show_percpuinfo = pmac_show_percpuinfo, .init_IRQ = pmac_pic_init, .get_irq = mpic_get_irq, /* changed later */ .pcibios_fixup = pmac_pcibios_fixup, diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 2130cc315957..94a81279deac 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -173,6 +173,16 @@ config KEXEC support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +source "drivers/cpufreq/Kconfig" + +config CPU_FREQ_PMAC64 + bool "Support for some Apple G5s" + depends on CPU_FREQ && PMAC_SMU && PPC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple iMac G5, + and some of the more recent desktop G5 machines as well. + config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 077507ffbab8..914632ec587d 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -560,7 +560,7 @@ _GLOBAL(real_readb) isync blr - /* +/* * Do an IO access in real mode */ _GLOBAL(real_writeb) @@ -592,6 +592,76 @@ _GLOBAL(real_writeb) blr #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ +/* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + ori r0,r4,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + isync + mfspr r0,SPRN_SCOMC + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + ori r0,r5,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd. + */ + + rlwinm r3,r3,8,0,15 + + sync + mtspr SPRN_SCOMD,r4 /* write data */ + isync + mtspr SPRN_SCOMC,r3 /* write command */ + isync + mfspr 3,SPRN_SCOMC + isync + + /* restore interrupts */ + mtmsrd r5,1 + blr + + /* * Create a kernel thread * kernel_thread(fn, arg, flags) diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 34f3c7e2d832..a931e508feb6 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -845,6 +845,18 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) return 0; } +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + char pname[32]; + + if (!smu) + return NULL; + + sprintf(pname, "sdb-partition-%02x", id); + return (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); +} +EXPORT_SYMBOL(smu_get_sdb_partition); /* diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index da848412f11b..489cf4c99c21 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -396,6 +396,9 @@ #define SPRN_VRSAVE 0x100 /* Vector Register Save Register */ #define SPRN_XER 0x001 /* Fixed Point Exception Register */ +#define SPRN_SCOMC 0x114 /* SCOM Access Control */ +#define SPRN_SCOMD 0x115 /* SCOM Access DATA */ + /* Performance monitor SPRs */ #ifdef CONFIG_PPC64 #define SPRN_MMCR0 795 @@ -594,7 +597,11 @@ static inline void ppc64_runlatch_off(void) mtspr(SPRN_CTRLT, ctrl); } } -#endif + +extern unsigned long scom970_read(unsigned int address); +extern void scom970_write(unsigned int address, unsigned long value); + +#endif /* CONFIG_PPC64 */ #define __get_SP() ({unsigned long sp; \ asm volatile("mr %0,1": "=r" (sp)); sp;}) diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index dee8eefe47bc..959bad660233 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -144,7 +144,11 @@ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is * used to set the voltage slewing point. The SMU replies with "DONE" * I yet have to figure out their exact meaning of those 3 bytes in - * both cases. + * both cases. They seem to be: + * x = processor mask + * y = op. point index + * z = processor freq. step index + * I haven't yet decyphered result codes * */ #define SMU_CMD_POWER_COMMAND 0xaa @@ -333,6 +337,60 @@ extern int smu_queue_i2c(struct smu_i2c_cmd *cmd); #endif /* __KERNEL__ */ + +/* + * - SMU "sdb" partitions informations - + */ + + +/* + * Partition header format + */ +struct smu_sdbp_header { + __u8 id; + __u8 len; + __u8 version; + __u8 flags; +}; + +/* + * 32 bits integers are usually encoded with 2x16 bits swapped, + * this demangles them + */ +#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) + +/* This is the definition of the SMU sdb-partition-0x12 table (called + * CPU F/V/T operating points in Darwin). The definition for all those + * SMU tables should be moved to some separate file + */ +#define SMU_SDB_FVT_ID 0x12 + +struct smu_sdbp_fvt { + __u32 sysclk; /* Base SysClk frequency in Hz for + * this operating point + */ + __u8 pad; + __u8 maxtemp; /* Max temp. supported by this + * operating point + */ + + __u16 volts[3]; /* CPU core voltage for the 3 + * PowerTune modes, a mode with + * 0V = not supported. + */ +}; + +#ifdef __KERNEL__ +/* + * This returns the pointer to an SMU "sdb" partition data or NULL + * if not found. The data format is described below + */ +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, + unsigned int *size); + +#endif /* __KERNEL__ */ + + /* * - Userland interface - */ -- cgit v1.2.3 From 183d020258dfd08178a05c6793dae10409db8abb Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:29:02 +1100 Subject: [PATCH] ppc64: SMU partition recovery This patch adds the ability to the SMU driver to recover missing calibration partitions from the SMU chip itself. It also adds some dynamic mecanism to /proc/device-tree so that new properties are visible to userland. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 21 +++++- arch/ppc/syslib/prom.c | 4 +- arch/ppc64/kernel/prom.c | 24 +++++-- drivers/macintosh/smu.c | 164 ++++++++++++++++++++++++++++++++++++++++++--- fs/proc/proc_devtree.c | 57 ++++++++++------ include/asm-powerpc/prom.h | 2 +- include/asm-powerpc/smu.h | 153 +++++++++++++++++++++++++++++++++++++++--- include/asm-ppc/prom.h | 2 +- include/asm-ppc64/prom.h | 2 +- include/linux/proc_fs.h | 9 +-- 10 files changed, 381 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 3675ef4bac90..f645adb57534 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1974,14 +1974,29 @@ EXPORT_SYMBOL(get_property); /* * Add a property to a node */ -void prom_add_property(struct device_node* np, struct property* prop) +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } /* I quickly hacked that one, check against spec ! */ diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 1b9aa0d6a924..03b1fc9b9501 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -1165,7 +1165,7 @@ get_property(struct device_node *np, const char *name, int *lenp) /* * Add a property to a node */ -void +int prom_add_property(struct device_node* np, struct property* prop) { struct property **next = &np->properties; @@ -1174,6 +1174,8 @@ prom_add_property(struct device_node* np, struct property* prop) while (*next) next = &(*next)->next; *next = prop; + + return 0; } /* I quickly hacked that one, check against spec ! */ diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 0e8961dea3bc..3402fbee62c7 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1865,17 +1866,32 @@ get_property(struct device_node *np, const char *name, int *lenp) EXPORT_SYMBOL(get_property); /* - * Add a property to a node + * Add a property to a node. */ -void +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } #if 0 diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index a931e508feb6..a83c4acf5710 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -47,13 +47,13 @@ #include #include -#define VERSION "0.6" +#define VERSION "0.7" #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." #undef DEBUG_SMU #ifdef DEBUG_SMU -#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) +#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0) #else #define DPRINTK(fmt, args...) do { } while (0) #endif @@ -92,7 +92,7 @@ struct smu_device { * for now, just hard code that */ static struct smu_device *smu; - +static DECLARE_MUTEX(smu_part_access); /* * SMU driver low level stuff @@ -113,9 +113,11 @@ static void smu_start_cmd(void) DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, cmd->data_len); - DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", + DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n", ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], - ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3], + ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5], + ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]); /* Fill the SMU command buffer */ smu->cmd_buf->cmd = cmd->cmd; @@ -440,7 +442,7 @@ int smu_present(void) EXPORT_SYMBOL(smu_present); -int smu_init (void) +int __init smu_init (void) { struct device_node *np; u32 *data; @@ -845,16 +847,154 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) return 0; } -struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +/* + * Handling of "partitions" + */ + +static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len) +{ + DECLARE_COMPLETION(comp); + unsigned int chunk; + struct smu_cmd cmd; + int rc; + u8 params[8]; + + /* We currently use a chunk size of 0xe. We could check the + * SMU firmware version and use bigger sizes though + */ + chunk = 0xe; + + while (len) { + unsigned int clen = min(len, chunk); + + cmd.cmd = SMU_CMD_MISC_ee_COMMAND; + cmd.data_len = 7; + cmd.data_buf = params; + cmd.reply_len = chunk; + cmd.reply_buf = dest; + cmd.done = smu_done_complete; + cmd.misc = ∁ + params[0] = SMU_CMD_MISC_ee_GET_DATABLOCK_REC; + params[1] = 0x4; + *((u32 *)¶ms[2]) = addr; + params[6] = clen; + + rc = smu_queue_cmd(&cmd); + if (rc) + return rc; + wait_for_completion(&comp); + if (cmd.status != 0) + return rc; + if (cmd.reply_len != clen) { + printk(KERN_DEBUG "SMU: short read in " + "smu_read_datablock, got: %d, want: %d\n", + cmd.reply_len, clen); + return -EIO; + } + len -= clen; + addr += clen; + dest += clen; + } + return 0; +} + +static struct smu_sdbp_header *smu_create_sdb_partition(int id) +{ + DECLARE_COMPLETION(comp); + struct smu_simple_cmd cmd; + unsigned int addr, len, tlen; + struct smu_sdbp_header *hdr; + struct property *prop; + + /* First query the partition info */ + smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, + smu_done_complete, &comp, + SMU_CMD_PARTITION_LATEST, id); + wait_for_completion(&comp); + + /* Partition doesn't exist (or other error) */ + if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) + return NULL; + + /* Fetch address and length from reply */ + addr = *((u16 *)cmd.buffer); + len = cmd.buffer[3] << 2; + /* Calucluate total length to allocate, including the 17 bytes + * for "sdb-partition-XX" that we append at the end of the buffer + */ + tlen = sizeof(struct property) + len + 18; + + prop = kcalloc(tlen, 1, GFP_KERNEL); + if (prop == NULL) + return NULL; + hdr = (struct smu_sdbp_header *)(prop + 1); + prop->name = ((char *)prop) + tlen - 18; + sprintf(prop->name, "sdb-partition-%02x", id); + prop->length = len; + prop->value = (unsigned char *)hdr; + prop->next = NULL; + + /* Read the datablock */ + if (smu_read_datablock((u8 *)hdr, addr, len)) { + printk(KERN_DEBUG "SMU: datablock read failed while reading " + "partition %02x !\n", id); + goto failure; + } + + /* Got it, check a few things and create the property */ + if (hdr->id != id) { + printk(KERN_DEBUG "SMU: Reading partition %02x and got " + "%02x !\n", id, hdr->id); + goto failure; + } + if (prom_add_property(smu->of_node, prop)) { + printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " + "property !\n", id); + goto failure; + } + + return hdr; + failure: + kfree(prop); + return NULL; +} + +/* Note: Only allowed to return error code in pointers (using ERR_PTR) + * when interruptible is 1 + */ +struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, + int interruptible) { char pname[32]; + struct smu_sdbp_header *part; if (!smu) return NULL; sprintf(pname, "sdb-partition-%02x", id); - return (struct smu_sdbp_header *)get_property(smu->of_node, + + if (interruptible) { + int rc; + rc = down_interruptible(&smu_part_access); + if (rc) + return ERR_PTR(rc); + } else + down(&smu_part_access); + + part = (struct smu_sdbp_header *)get_property(smu->of_node, pname, size); + if (part == NULL) { + part = smu_create_sdb_partition(id); + if (part != NULL && size) + *size = part->len << 2; + } + up(&smu_part_access); + return part; +} + +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + return __smu_get_sdb_partition(id, size, 0); } EXPORT_SYMBOL(smu_get_sdb_partition); @@ -930,6 +1070,14 @@ static ssize_t smu_write(struct file *file, const char __user *buf, else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { pp->mode = smu_file_events; return 0; + } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { + struct smu_sdbp_header *part; + part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); + if (part == NULL) + return -EINVAL; + else if (IS_ERR(part)) + return PTR_ERR(part); + return 0; } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) return -EINVAL; else if (pp->mode != smu_file_commands) diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 6fd57f154197..fb117b74809e 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -48,6 +48,39 @@ static int property_read_proc(char *page, char **start, off_t off, * and "@10" to it. */ +/* + * Add a property to a node + */ +static struct proc_dir_entry * +__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) +{ + struct proc_dir_entry *ent; + + /* + * Unfortunately proc_register puts each new entry + * at the beginning of the list. So we rearrange them. + */ + ent = create_proc_read_entry(pp->name, + strncmp(pp->name, "security-", 9) + ? S_IRUGO : S_IRUSR, de, + property_read_proc, pp); + if (ent == NULL) + return NULL; + + if (!strncmp(pp->name, "security-", 9)) + ent->size = 0; /* don't leak number of password chars */ + else + ent->size = pp->length; + + return ent; +} + + +void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) +{ + __proc_device_tree_add_prop(pde, prop); +} + /* * Process a node, adding entries for its children and its properties. */ @@ -57,11 +90,9 @@ void proc_device_tree_add_node(struct device_node *np, struct property *pp; struct proc_dir_entry *ent; struct device_node *child; - struct proc_dir_entry *list = NULL, **lastp; const char *p; set_node_proc_entry(np, de); - lastp = &list; for (child = NULL; (child = of_get_next_child(np, child));) { p = strrchr(child->full_name, '/'); if (!p) @@ -71,9 +102,6 @@ void proc_device_tree_add_node(struct device_node *np, ent = proc_mkdir(p, de); if (ent == 0) break; - *lastp = ent; - ent->next = NULL; - lastp = &ent->next; proc_device_tree_add_node(child, ent); } of_node_put(child); @@ -84,7 +112,7 @@ void proc_device_tree_add_node(struct device_node *np, * properties are quite unimportant for us though, thus we * simply "skip" them here, but we do have to check. */ - for (ent = list; ent != NULL; ent = ent->next) + for (ent = de->subdir; ent != NULL; ent = ent->next) if (!strcmp(ent->name, pp->name)) break; if (ent != NULL) { @@ -94,25 +122,10 @@ void proc_device_tree_add_node(struct device_node *np, continue; } - /* - * Unfortunately proc_register puts each new entry - * at the beginning of the list. So we rearrange them. - */ - ent = create_proc_read_entry(pp->name, - strncmp(pp->name, "security-", 9) - ? S_IRUGO : S_IRUSR, de, - property_read_proc, pp); + ent = __proc_device_tree_add_prop(de, pp); if (ent == 0) break; - if (!strncmp(pp->name, "security-", 9)) - ent->size = 0; /* don't leak number of password chars */ - else - ent->size = pp->length; - ent->next = NULL; - *lastp = ent; - lastp = &ent->next; } - de->subdir = list; } /* diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 7587bf5f38c6..f999df1c5c90 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -203,7 +203,7 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #ifdef CONFIG_PPC32 /* diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index 959bad660233..76c29a9784dd 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -20,16 +20,52 @@ /* * Partition info commands * - * I do not know what those are for at this point + * These commands are used to retreive the sdb-partition-XX datas from + * the SMU. The lenght is always 2. First byte is the subcommand code + * and second byte is the partition ID. + * + * The reply is 6 bytes: + * + * - 0..1 : partition address + * - 2 : a byte containing the partition ID + * - 3 : length (maybe other bits are rest of header ?) + * + * The data must then be obtained with calls to another command: + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC (described below). */ #define SMU_CMD_PARTITION_COMMAND 0x3e +#define SMU_CMD_PARTITION_LATEST 0x01 +#define SMU_CMD_PARTITION_BASE 0x02 +#define SMU_CMD_PARTITION_UPDATE 0x03 /* * Fan control * - * This is a "mux" for fan control commands, first byte is the - * "sub" command. + * This is a "mux" for fan control commands. The command seem to + * act differently based on the number of arguments. With 1 byte + * of argument, this seem to be queries for fans status, setpoint, + * etc..., while with 0xe arguments, we will set the fans speeds. + * + * Queries (1 byte arg): + * --------------------- + * + * arg=0x01: read RPM fans status + * arg=0x02: read RPM fans setpoint + * arg=0x11: read PWM fans status + * arg=0x12: read PWM fans setpoint + * + * the "status" queries return the current speed while the "setpoint" ones + * return the programmed/target speed. It _seems_ that the result is a bit + * mask in the first byte of active/available fans, followed by 6 words (16 + * bits) containing the requested speed. + * + * Setpoint (14 bytes arg): + * ------------------------ + * + * first arg byte is 0 for RPM fans and 0x10 for PWM. Second arg byte is the + * mask of fans affected by the command. Followed by 6 words containing the + * setpoint value for selected fans in the mask (or 0 if mask value is 0) */ #define SMU_CMD_FAN_COMMAND 0x4a @@ -156,6 +192,14 @@ #define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" #define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" +/* + * Read ADC sensors + * + * This command takes one byte of parameter: the sensor ID (or "reg" + * value in the device-tree) and returns a 16 bits value + */ +#define SMU_CMD_READ_ADC 0xd8 + /* Misc commands * * This command seem to be a grab bag of various things @@ -176,6 +220,25 @@ * Misc commands * * This command seem to be a grab bag of various things + * + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to + * transfer blocks of data from the SMU. So far, I've decrypted it's + * usage to retreive partition data. In order to do that, you have to + * break your transfer in "chunks" since that command cannot transfer + * more than a chunk at a time. The chunk size used by OF is 0xe bytes, + * but it seems that the darwin driver will let you do 0x1e bytes if + * your "PMU" version is >= 0x30. You can get the "PMU" version apparently + * either in the last 16 bits of property "smu-version-pmu" or as the 16 + * bytes at offset 1 of "smu-version-info" + * + * For each chunk, the command takes 7 bytes of arguments: + * byte 0: subcommand code (0x02) + * byte 1: 0x04 (always, I don't know what it means, maybe the address + * space to use or some other nicety. It's hard coded in OF) + * byte 2..5: SMU address of the chunk (big endian 32 bits) + * byte 6: size to transfer (up to max chunk size) + * + * The data is returned directly */ #define SMU_CMD_MISC_ee_COMMAND 0xee #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 @@ -353,21 +416,26 @@ struct smu_sdbp_header { __u8 flags; }; -/* - * 32 bits integers are usually encoded with 2x16 bits swapped, - * this demangles them + + /* + * demangle 16 and 32 bits integer in some SMU partitions + * (currently, afaik, this concerns only the FVT partition + * (0x12) */ -#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) +#define SMU_U16_MIX(x) le16_to_cpu(x); +#define SMU_U32_MIX(x) ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8)) + /* This is the definition of the SMU sdb-partition-0x12 table (called * CPU F/V/T operating points in Darwin). The definition for all those * SMU tables should be moved to some separate file */ -#define SMU_SDB_FVT_ID 0x12 +#define SMU_SDB_FVT_ID 0x12 struct smu_sdbp_fvt { __u32 sysclk; /* Base SysClk frequency in Hz for - * this operating point + * this operating point. Value need to + * be unmixed with SMU_U32_MIX() */ __u8 pad; __u8 maxtemp; /* Max temp. supported by this @@ -376,10 +444,73 @@ struct smu_sdbp_fvt { __u16 volts[3]; /* CPU core voltage for the 3 * PowerTune modes, a mode with - * 0V = not supported. + * 0V = not supported. Value need + * to be unmixed with SMU_U16_MIX() */ }; +/* This partition contains voltage & current sensor calibration + * informations + */ +#define SMU_SDB_CPUVCP_ID 0x21 + +struct smu_sdbp_cpuvcp { + __u16 volt_scale; /* u4.12 fixed point */ + __s16 volt_offset; /* s4.12 fixed point */ + __u16 curr_scale; /* u4.12 fixed point */ + __s16 curr_offset; /* s4.12 fixed point */ + __s32 power_quads[3]; /* s4.28 fixed point */ +}; + +/* This partition contains CPU thermal diode calibration + */ +#define SMU_SDB_CPUDIODE_ID 0x18 + +struct smu_sdbp_cpudiode { + __u16 m_value; /* u1.15 fixed point */ + __s16 b_value; /* s10.6 fixed point */ + +}; + +/* This partition contains Slots power calibration + */ +#define SMU_SDB_SLOTSPOW_ID 0x78 + +struct smu_sdbp_slotspow { + __u16 pow_scale; /* u4.12 fixed point */ + __s16 pow_offset; /* s4.12 fixed point */ +}; + +/* This partition contains machine specific version information about + * the sensor/control layout + */ +#define SMU_SDB_SENSORTREE_ID 0x25 + +struct smu_sdbp_sensortree { + u8 model_id; + u8 unknown[3]; +}; + +/* This partition contains CPU thermal control PID informations. So far + * only single CPU machines have been seen with an SMU, so we assume this + * carries only informations for those + */ +#define SMU_SDB_CPUPIDDATA_ID 0x17 + +struct smu_sdbp_cpupiddata { + u8 unknown1; + u8 target_temp_delta; + u8 unknown2; + u8 history_len; + s16 power_adj; + u16 max_power; + s32 gp,gr,gd; +}; + + +/* Other partitions without known structures */ +#define SMU_SDB_DEBUG_SWITCHES_ID 0x05 + #ifdef __KERNEL__ /* * This returns the pointer to an SMU "sdb" partition data or NULL @@ -423,8 +554,10 @@ struct smu_user_cmd_hdr __u32 cmdtype; #define SMU_CMDTYPE_SMU 0 /* SMU command */ #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ +#define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ __u8 cmd; /* SMU command byte */ + __u8 pad[3]; /* padding */ __u32 data_len; /* Lenght of data following */ }; diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index 75c0637acdc8..3e39827ed566 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h @@ -93,7 +93,7 @@ extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); extern unsigned char *get_property(struct device_node *node, const char *name, int *lenp); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); extern void prom_get_irq_senses(unsigned char *, int, int); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index bdb47174ff0e..76bb0266d67c 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -213,6 +213,6 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #endif /* _PPC64_PROM_H */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 0563581e3a02..65ceeaa30652 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -139,15 +139,12 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver); /* * proc_devtree.c */ +#ifdef CONFIG_PROC_DEVICETREE struct device_node; +struct property; extern void proc_device_tree_init(void); -#ifdef CONFIG_PROC_DEVICETREE extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); -#else /* !CONFIG_PROC_DEVICETREE */ -static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) -{ - return; -} +extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); #endif /* CONFIG_PROC_DEVICETREE */ extern struct proc_dir_entry *proc_symlink(const char *, -- cgit v1.2.3 From 21fe3301f11a93c4f18e8480ed08522559bf0a50 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 16:41:59 +1100 Subject: [PATCH] ppc: fix a bunch of warnings Building a PowerMac kernel with ARCH=powerpc causes a bunch of warnings, this fixes some of them Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 9 +++++---- arch/powerpc/kernel/rtas.c | 3 ++- drivers/macintosh/via-pmu.c | 6 +++--- include/asm-powerpc/xmon.h | 1 + include/asm-ppc/btext.h | 22 +++++++++++----------- 5 files changed, 22 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 0d91961f9433..6dc33d19fc2a 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -403,19 +403,19 @@ static int __init prom_next_node(phandle *nodep) } } -static int __init prom_getprop(phandle node, const char *pname, +static int inline prom_getprop(phandle node, const char *pname, void *value, size_t valuelen) { return call_prom("getprop", 4, 1, node, ADDR(pname), (u32)(unsigned long) value, (u32) valuelen); } -static int __init prom_getproplen(phandle node, const char *pname) +static int inline prom_getproplen(phandle node, const char *pname) { return call_prom("getproplen", 2, 1, node, ADDR(pname)); } -static int __init prom_setprop(phandle node, const char *pname, +static int inline prom_setprop(phandle node, const char *pname, void *value, size_t valuelen) { return call_prom("setprop", 4, 1, node, ADDR(pname), @@ -1408,8 +1408,9 @@ static int __init prom_find_machine_type(void) struct prom_t *_prom = &RELOC(prom); char compat[256]; int len, i = 0; +#ifdef CONFIG_PPC64 phandle rtas; - +#endif len = prom_getprop(_prom->root, "compatible", compat, sizeof(compat)-1); if (len > 0) { diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 751f5ddea913..9d4e07f6f1ec 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -83,7 +84,7 @@ void call_rtas_display_status_delay(unsigned char c) while (width-- > 0) call_rtas_display_status(' '); width = 16; - udelay(500000); + mdelay(500); pending_newline = 1; } else { if (pending_newline) { diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 9bc6cc6e3845..7ebbc0f53420 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2667,10 +2667,10 @@ powerbook_sleep_3400(void) asleep = 1; /* Put the CPU into sleep mode */ - asm volatile("mfspr %0,1008" : "=r" (hid0) :); + hid0 = mfspr(SPRN_HID0); hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; - asm volatile("mtspr 1008,%0" : : "r" (hid0)); - _nmask_and_or_msr(0, MSR_POW | MSR_EE); + mtspr(SPRN_HID0, hid0); + mtmsr(mfmsr() | MSR_POW | MSR_EE); udelay(10); /* OK, we're awake again, start restoring things */ diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index 43f7129984c7..ace2072d4a83 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h @@ -7,6 +7,7 @@ struct pt_regs; extern int xmon(struct pt_regs *excp); extern void xmon_printf(const char *fmt, ...); extern void xmon_init(int); +extern void xmon_map_scc(void); #endif #endif diff --git a/include/asm-ppc/btext.h b/include/asm-ppc/btext.h index 36c7640d00f2..ccaefabe0bf5 100644 --- a/include/asm-ppc/btext.h +++ b/include/asm-ppc/btext.h @@ -17,18 +17,18 @@ extern unsigned long disp_BAT[2]; extern boot_infos_t disp_bi; extern int boot_text_mapped; -void btext_init(boot_infos_t *bi); -void btext_welcome(void); -void btext_prepare_BAT(void); -void btext_setup_display(int width, int height, int depth, int pitch, - unsigned long address); -void map_boot_text(void); -void btext_update_display(unsigned long phys, int width, int height, - int depth, int pitch); +extern void init_boot_display(void); +extern void btext_welcome(void); +extern void btext_prepare_BAT(void); +extern void btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address); +extern void map_boot_text(void); +extern void btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch); -void btext_drawchar(char c); -void btext_drawstring(const char *str); -void btext_drawhex(unsigned long v); +extern void btext_drawchar(char c); +extern void btext_drawstring(const char *str); +extern void btext_drawhex(unsigned long v); #endif /* __KERNEL__ */ #endif /* __PPC_BTEXT_H */ -- cgit v1.2.3 From 7b007de8a90604000329154e87d269db3427d099 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 16:43:44 +1100 Subject: [PATCH] ppc: Fix ARCH=ppc build with xmon xmon() prototype is inconsistent between ARCH=ppc and ARCH=powerpc, thus causing ARCH=ppc build breakage. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/ppc/kernel/traps.c | 4 ++-- arch/ppc/xmon/xmon.c | 5 +++-- include/asm-ppc/kgdb.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 42d980e82bdc..9dbc4d28fa28 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -49,7 +49,7 @@ extern int xmon_sstep(struct pt_regs *regs); extern int xmon_iabr_match(struct pt_regs *regs); extern int xmon_dabr_match(struct pt_regs *regs); -void (*debugger)(struct pt_regs *regs) = xmon; +int (*debugger)(struct pt_regs *regs) = xmon; int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt; int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep; int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match; @@ -57,7 +57,7 @@ int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match; void (*debugger_fault_handler)(struct pt_regs *regs); #else #ifdef CONFIG_KGDB -void (*debugger)(struct pt_regs *regs); +int (*debugger)(struct pt_regs *regs); int (*debugger_bpt)(struct pt_regs *regs); int (*debugger_sstep)(struct pt_regs *regs); int (*debugger_iabr_match)(struct pt_regs *regs); diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 66bfaa3211a2..2b483b4f1602 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -220,8 +220,7 @@ static void get_tb(unsigned *p) p[1] = lo; } -void -xmon(struct pt_regs *excp) +int xmon(struct pt_regs *excp) { struct pt_regs regs; int msr, cmd; @@ -290,6 +289,8 @@ xmon(struct pt_regs *excp) #endif /* CONFIG_SMP */ set_msr(msr); /* restore interrupt enable */ get_tb(start_tb[smp_processor_id()]); + + return cmd != 'X'; } irqreturn_t diff --git a/include/asm-ppc/kgdb.h b/include/asm-ppc/kgdb.h index 1d3c927ce626..b617dac82969 100644 --- a/include/asm-ppc/kgdb.h +++ b/include/asm-ppc/kgdb.h @@ -31,7 +31,7 @@ extern void breakpoint(void); /* For taking exceptions * these are defined in traps.c */ -extern void (*debugger)(struct pt_regs *regs); +extern int (*debugger)(struct pt_regs *regs); extern int (*debugger_bpt)(struct pt_regs *regs); extern int (*debugger_sstep)(struct pt_regs *regs); extern int (*debugger_iabr_match)(struct pt_regs *regs); -- cgit v1.2.3 From b354cab0763080df3735dcd0c64a545f266cc9e2 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 8 Nov 2005 12:20:34 +1100 Subject: powerpc: merge ide.h This is very simple with it being almost all ppc32 with just a couple of common defines. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- include/asm-powerpc/ide.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/ide.h | 78 -------------------------------------------- include/asm-ppc64/ide.h | 30 ----------------- 3 files changed, 83 insertions(+), 108 deletions(-) create mode 100644 include/asm-powerpc/ide.h delete mode 100644 include/asm-ppc/ide.h delete mode 100644 include/asm-ppc64/ide.h (limited to 'include') diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h new file mode 100644 index 000000000000..da5f640480cf --- /dev/null +++ b/include/asm-powerpc/ide.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 1994-1996 Linus Torvalds & authors + * + * This file contains the powerpc architecture specific IDE code. + */ +#ifndef _ASM_POWERPC_IDE_H +#define _ASM_POWERPC_IDE_H + +#ifdef __KERNEL__ + +#ifndef __powerpc64__ +#include +#include +#endif + +#ifndef MAX_HWIFS +#ifdef __powerpc64__ +#define MAX_HWIFS 10 +#else +#define MAX_HWIFS 8 +#endif +#endif + +#ifndef __powerpc64__ +#include +#include +#include +#include + +extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count); + +struct ide_machdep_calls { + int (*default_irq)(unsigned long base); + unsigned long (*default_io_base)(int index); + void (*ide_init_hwif)(hw_regs_t *hw, + unsigned long data_port, + unsigned long ctrl_port, + int *irq); +}; + +extern struct ide_machdep_calls ppc_ide_md; + +#undef SUPPORT_SLOW_DATA_PORTS +#define SUPPORT_SLOW_DATA_PORTS 0 + +#define IDE_ARCH_OBSOLETE_DEFAULTS + +static __inline__ int ide_default_irq(unsigned long base) +{ + if (ppc_ide_md.default_irq) + return ppc_ide_md.default_irq(base); + return 0; +} + +static __inline__ unsigned long ide_default_io_base(int index) +{ + if (ppc_ide_md.default_io_base) + return ppc_ide_md.default_io_base(index); + return 0; +} + +#ifdef CONFIG_PCI +#define ide_init_default_irq(base) (0) +#else +#define ide_init_default_irq(base) ide_default_irq(base) +#endif + +#if (defined CONFIG_APUS || defined CONFIG_BLK_DEV_MPC8xx_IDE ) +#define IDE_ARCH_ACK_INTR 1 +#define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) +#endif + +#endif /* __powerpc64__ */ + +#define IDE_ARCH_OBSOLETE_INIT +#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_IDE_H */ diff --git a/include/asm-ppc/ide.h b/include/asm-ppc/ide.h deleted file mode 100644 index 7d6e6599fac4..000000000000 --- a/include/asm-ppc/ide.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * linux/include/asm-ppc/ide.h - * - * Copyright (C) 1994-1996 Linus Torvalds & authors */ - -/* - * This file contains the ppc architecture specific IDE code. - */ - -#ifndef __ASMPPC_IDE_H -#define __ASMPPC_IDE_H - -#ifdef __KERNEL__ - -#include -#include - -#ifndef MAX_HWIFS -#define MAX_HWIFS 8 -#endif - -#include -#include -#include -#include - -extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count); -extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count); -extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count); -extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count); - -struct ide_machdep_calls { - int (*default_irq)(unsigned long base); - unsigned long (*default_io_base)(int index); - void (*ide_init_hwif)(hw_regs_t *hw, - unsigned long data_port, - unsigned long ctrl_port, - int *irq); -}; - -extern struct ide_machdep_calls ppc_ide_md; - -#undef SUPPORT_SLOW_DATA_PORTS -#define SUPPORT_SLOW_DATA_PORTS 0 - -#define IDE_ARCH_OBSOLETE_DEFAULTS - -static __inline__ int ide_default_irq(unsigned long base) -{ - if (ppc_ide_md.default_irq) - return ppc_ide_md.default_irq(base); - return 0; -} - -static __inline__ unsigned long ide_default_io_base(int index) -{ - if (ppc_ide_md.default_io_base) - return ppc_ide_md.default_io_base(index); - return 0; -} - -#define IDE_ARCH_OBSOLETE_INIT -#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ - -#ifdef CONFIG_PCI -#define ide_init_default_irq(base) (0) -#else -#define ide_init_default_irq(base) ide_default_irq(base) -#endif - -#if (defined CONFIG_APUS || defined CONFIG_BLK_DEV_MPC8xx_IDE ) -#define IDE_ARCH_ACK_INTR 1 -#define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) -#endif - -#endif /* __KERNEL__ */ - -#endif /* __ASMPPC_IDE_H */ diff --git a/include/asm-ppc64/ide.h b/include/asm-ppc64/ide.h deleted file mode 100644 index 0aae1c590c0e..000000000000 --- a/include/asm-ppc64/ide.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * linux/include/asm-ppc/ide.h - * - * Copyright (C) 1994-1996 Linus Torvalds & authors - * - * 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. - */ - -/* - * This file contains the ppc64 architecture specific IDE code. - */ - -#ifndef __ASMPPC64_IDE_H -#define __ASMPPC64_IDE_H - -#ifdef __KERNEL__ - -#ifndef MAX_HWIFS -# define MAX_HWIFS 10 -#endif - -#define IDE_ARCH_OBSOLETE_INIT -#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ - -#endif /* __KERNEL__ */ - -#endif /* __ASMPPC64_IDE_H */ -- cgit v1.2.3 From 7b7b1ace2d9d06d76bce7481a045c22ed75e35dd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:13:39 -0500 Subject: [PATCH] saner handling of auto_acct_off() and DQUOT_OFF() in umount The way we currently deal with quota and process accounting that might keep vfsmount busy at umount time is inherently broken; we try to turn them off just in case (not quite correctly, at that) and a) pray umount doesn't fail (otherwise they'll stay turned off) b) pray nobody doesn anything funny just as we turn quota off Moreover, LSM provides hooks for doing the same sort of broken logics. The proper way to deal with that is to introduce the second kind of reference to vfsmount. Semantics: - when the last normal reference is dropped, all special ones are converted to normal ones and if there had been any, cleanup is done. - normal reference can be cloned into a special one - special reference can be converted to normal one; that's a no-op if we'd already passed the point of no return (i.e. mntput() had converted special references to normal and started cleanup). The way it works: e.g. starting process accounting converts the vfsmount reference pinned by the opened file into special one and turns it back to normal when it gets shut down; acct_auto_close() is done when no normal references are left. That way it does *not* obstruct umount(2) and it silently gets turned off when the last normal reference to vfsmount is gone. Which is exactly what we want... The same should be done by LSM module that holds some internal references to vfsmount and wants to shut them down on umount - it should make them special and security_sb_umount_close() will be called exactly when the last normal reference to vfsmount is gone. quota handling is even simpler - we don't use normal file IO anymore, so there's no need to hold vfsmounts at all. DQUOT_OFF() is done from deactivate_super(), where it really belongs. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/dquot.c | 18 ++-------- fs/namespace.c | 64 ++++++++++++++++++++++------------- fs/super.c | 1 + include/linux/acct.h | 3 ++ include/linux/mount.h | 13 +++----- include/linux/quota.h | 1 - kernel/acct.c | 92 ++++++++++++++++++++++++++++++++++----------------- 7 files changed, 113 insertions(+), 79 deletions(-) (limited to 'include') diff --git a/fs/dquot.c b/fs/dquot.c index afa06a893468..05b60283c9c2 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1321,13 +1321,11 @@ int vfs_quota_off(struct super_block *sb, int type) int cnt; struct quota_info *dqopt = sb_dqopt(sb); struct inode *toputinode[MAXQUOTAS]; - struct vfsmount *toputmnt[MAXQUOTAS]; /* We need to serialize quota_off() for device */ down(&dqopt->dqonoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { toputinode[cnt] = NULL; - toputmnt[cnt] = NULL; if (type != -1 && cnt != type) continue; if (!sb_has_quota_enabled(sb, cnt)) @@ -1348,9 +1346,7 @@ int vfs_quota_off(struct super_block *sb, int type) put_quota_format(dqopt->info[cnt].dqi_format); toputinode[cnt] = dqopt->files[cnt]; - toputmnt[cnt] = dqopt->mnt[cnt]; dqopt->files[cnt] = NULL; - dqopt->mnt[cnt] = NULL; dqopt->info[cnt].dqi_flags = 0; dqopt->info[cnt].dqi_igrace = 0; dqopt->info[cnt].dqi_bgrace = 0; @@ -1358,10 +1354,7 @@ int vfs_quota_off(struct super_block *sb, int type) } up(&dqopt->dqonoff_sem); /* Sync the superblock so that buffers with quota data are written to - * disk (and so userspace sees correct data afterwards). - * The reference to vfsmnt we are still holding protects us from - * umount (we don't have it only when quotas are turned on/off for - * journal replay but in that case we are guarded by the fs anyway). */ + * disk (and so userspace sees correct data afterwards). */ if (sb->s_op->sync_fs) sb->s_op->sync_fs(sb, 1); sync_blockdev(sb->s_bdev); @@ -1385,10 +1378,6 @@ int vfs_quota_off(struct super_block *sb, int type) iput(toputinode[cnt]); } up(&dqopt->dqonoff_sem); - /* We don't hold the reference when we turned on quotas - * just for the journal replay... */ - if (toputmnt[cnt]) - mntput(toputmnt[cnt]); } if (sb->s_bdev) invalidate_bdev(sb->s_bdev, 0); @@ -1503,11 +1492,8 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) /* Quota file not on the same filesystem? */ if (nd.mnt->mnt_sb != sb) error = -EXDEV; - else { + else error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); - if (!error) - sb_dqopt(sb)->mnt[type] = mntget(nd.mnt); - } out_path: path_release(&nd); return error; diff --git a/fs/namespace.c b/fs/namespace.c index 2fa9fdf7d6f5..1d83302f30c3 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -172,7 +172,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root) return mnt; } -void __mntput(struct vfsmount *mnt) +static inline void __mntput(struct vfsmount *mnt) { struct super_block *sb = mnt->mnt_sb; dput(mnt->mnt_root); @@ -180,7 +180,46 @@ void __mntput(struct vfsmount *mnt) deactivate_super(sb); } -EXPORT_SYMBOL(__mntput); +void mntput_no_expire(struct vfsmount *mnt) +{ +repeat: + if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock)) { + if (likely(!mnt->mnt_pinned)) { + spin_unlock(&vfsmount_lock); + __mntput(mnt); + return; + } + atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count); + mnt->mnt_pinned = 0; + spin_unlock(&vfsmount_lock); + acct_auto_close_mnt(mnt); + security_sb_umount_close(mnt); + goto repeat; + } +} + +EXPORT_SYMBOL(mntput_no_expire); + +void mnt_pin(struct vfsmount *mnt) +{ + spin_lock(&vfsmount_lock); + mnt->mnt_pinned++; + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL(mnt_pin); + +void mnt_unpin(struct vfsmount *mnt) +{ + spin_lock(&vfsmount_lock); + if (mnt->mnt_pinned) { + atomic_inc(&mnt->mnt_count); + mnt->mnt_pinned--; + } + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL(mnt_unpin); /* iterator */ static void *m_start(struct seq_file *m, loff_t *pos) @@ -435,16 +474,6 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(¤t->namespace->sem); spin_lock(&vfsmount_lock); - if (atomic_read(&sb->s_active) == 1) { - /* last instance - try to be smart */ - spin_unlock(&vfsmount_lock); - lock_kernel(); - DQUOT_OFF(sb); - acct_auto_close(sb); - unlock_kernel(); - security_sb_umount_close(mnt); - spin_lock(&vfsmount_lock); - } retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { if (!list_empty(&mnt->mnt_list)) @@ -850,17 +879,6 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) detach_mnt(mnt, &old_nd); spin_unlock(&vfsmount_lock); path_release(&old_nd); - - /* - * Now lay it to rest if this was the last ref on the superblock - */ - if (atomic_read(&mnt->mnt_sb->s_active) == 1) { - /* last instance - try to be smart */ - lock_kernel(); - DQUOT_OFF(mnt->mnt_sb); - acct_auto_close(mnt->mnt_sb); - unlock_kernel(); - } mntput(mnt); } else { /* diff --git a/fs/super.c b/fs/super.c index eed6c3132905..6689dded3c84 100644 --- a/fs/super.c +++ b/fs/super.c @@ -171,6 +171,7 @@ void deactivate_super(struct super_block *s) if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { s->s_count -= S_BIAS-1; spin_unlock(&sb_lock); + DQUOT_OFF(s); down_write(&s->s_umount); fs->kill_sb(s); put_filesystem(fs); diff --git a/include/linux/acct.h b/include/linux/acct.h index 19f70462b3be..93c5b3cdf951 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h @@ -117,12 +117,15 @@ struct acct_v3 #include #ifdef CONFIG_BSD_PROCESS_ACCT +struct vfsmount; struct super_block; +extern void acct_auto_close_mnt(struct vfsmount *m); extern void acct_auto_close(struct super_block *sb); extern void acct_process(long exitcode); extern void acct_update_integrals(struct task_struct *tsk); extern void acct_clear_integrals(struct task_struct *tsk); #else +#define acct_auto_close_mnt(x) do { } while (0) #define acct_auto_close(x) do { } while (0) #define acct_process(x) do { } while (0) #define acct_update_integrals(x) do { } while (0) diff --git a/include/linux/mount.h b/include/linux/mount.h index f8f39937e301..ffb0b5089880 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -37,6 +37,7 @@ struct vfsmount struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct namespace *mnt_namespace; /* containing namespace */ + int mnt_pinned; }; static inline struct vfsmount *mntget(struct vfsmount *mnt) @@ -46,15 +47,9 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) return mnt; } -extern void __mntput(struct vfsmount *mnt); - -static inline void mntput_no_expire(struct vfsmount *mnt) -{ - if (mnt) { - if (atomic_dec_and_test(&mnt->mnt_count)) - __mntput(mnt); - } -} +extern void mntput_no_expire(struct vfsmount *mnt); +extern void mnt_pin(struct vfsmount *mnt); +extern void mnt_unpin(struct vfsmount *mnt); static inline void mntput(struct vfsmount *mnt) { diff --git a/include/linux/quota.h b/include/linux/quota.h index 700ead45084f..f33aeb22c26a 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -289,7 +289,6 @@ struct quota_info { struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ - struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ }; diff --git a/kernel/acct.c b/kernel/acct.c index 2e3f4a47e7d0..6312d6bd43e3 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include /* sector_div */ @@ -192,6 +193,7 @@ static void acct_file_reopen(struct file *file) add_timer(&acct_globals.timer); } if (old_acct) { + mnt_unpin(old_acct->f_vfsmnt); spin_unlock(&acct_globals.lock); do_acct_process(0, old_acct); filp_close(old_acct, NULL); @@ -199,6 +201,42 @@ static void acct_file_reopen(struct file *file) } } +static int acct_on(char *name) +{ + struct file *file; + int error; + + /* Difference from BSD - they don't do O_APPEND */ + file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); + if (IS_ERR(file)) + return PTR_ERR(file); + + if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { + filp_close(file, NULL); + return -EACCES; + } + + if (!file->f_op->write) { + filp_close(file, NULL); + return -EIO; + } + + error = security_acct(file); + if (error) { + filp_close(file, NULL); + return error; + } + + spin_lock(&acct_globals.lock); + mnt_pin(file->f_vfsmnt); + acct_file_reopen(file); + spin_unlock(&acct_globals.lock); + + mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */ + + return 0; +} + /** * sys_acct - enable/disable process accounting * @name: file name for accounting records or NULL to shutdown accounting @@ -212,47 +250,41 @@ static void acct_file_reopen(struct file *file) */ asmlinkage long sys_acct(const char __user *name) { - struct file *file = NULL; - char *tmp; int error; if (!capable(CAP_SYS_PACCT)) return -EPERM; if (name) { - tmp = getname(name); - if (IS_ERR(tmp)) { + char *tmp = getname(name); + if (IS_ERR(tmp)) return (PTR_ERR(tmp)); - } - /* Difference from BSD - they don't do O_APPEND */ - file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0); + error = acct_on(tmp); putname(tmp); - if (IS_ERR(file)) { - return (PTR_ERR(file)); - } - if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { - filp_close(file, NULL); - return (-EACCES); - } - - if (!file->f_op->write) { - filp_close(file, NULL); - return (-EIO); + } else { + error = security_acct(NULL); + if (!error) { + spin_lock(&acct_globals.lock); + acct_file_reopen(NULL); + spin_unlock(&acct_globals.lock); } } + return error; +} - error = security_acct(file); - if (error) { - if (file) - filp_close(file, NULL); - return error; - } - +/** + * acct_auto_close - turn off a filesystem's accounting if it is on + * @m: vfsmount being shut down + * + * If the accounting is turned on for a file in the subtree pointed to + * to by m, turn accounting off. Done when m is about to die. + */ +void acct_auto_close_mnt(struct vfsmount *m) +{ spin_lock(&acct_globals.lock); - acct_file_reopen(file); + if (acct_globals.file && acct_globals.file->f_vfsmnt == m) + acct_file_reopen(NULL); spin_unlock(&acct_globals.lock); - - return (0); } /** @@ -266,8 +298,8 @@ void acct_auto_close(struct super_block *sb) { spin_lock(&acct_globals.lock); if (acct_globals.file && - acct_globals.file->f_dentry->d_inode->i_sb == sb) { - acct_file_reopen((struct file *)NULL); + acct_globals.file->f_vfsmnt->mnt_sb == sb) { + acct_file_reopen(NULL); } spin_unlock(&acct_globals.lock); } -- cgit v1.2.3 From 5addc5dd8836aa061f6efc4a0d9ba6323726297a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:15:49 -0500 Subject: [PATCH] make /proc/mounts pollable Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 30 ++++++++++++++++++++++- fs/proc/base.c | 62 +++++++++++++++++++++++++++++++++++------------ include/linux/namespace.h | 2 ++ 3 files changed, 78 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 611f777bbd61..d1aca685aacf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -37,7 +37,9 @@ static inline int sysfs_init(void) #endif /* spinlock for vfsmount related operations, inplace of dcache_lock */ - __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); + +static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; @@ -111,6 +113,22 @@ static inline int check_mnt(struct vfsmount *mnt) return mnt->mnt_namespace == current->namespace; } +static void touch_namespace(struct namespace *ns) +{ + if (ns) { + ns->event = ++event; + wake_up_interruptible(&ns->poll); + } +} + +static void __touch_namespace(struct namespace *ns) +{ + if (ns && ns->event != event) { + ns->event = event; + wake_up_interruptible(&ns->poll); + } +} + static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) { old_nd->dentry = mnt->mnt_mountpoint; @@ -384,6 +402,7 @@ static void umount_tree(struct vfsmount *mnt) for (p = mnt; p; p = next_mnt(p, mnt)) { list_del(&p->mnt_list); list_add(&p->mnt_list, &kill); + __touch_namespace(p->mnt_namespace); p->mnt_namespace = NULL; } @@ -473,6 +492,7 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(¤t->namespace->sem); spin_lock(&vfsmount_lock); + event++; retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { @@ -634,6 +654,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) list_splice(&head, current->namespace->list.prev); mntget(mnt); err = 0; + touch_namespace(current->namespace); } spin_unlock(&vfsmount_lock); out_unlock: @@ -771,6 +792,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) detach_mnt(old_nd.mnt, &parent_nd); attach_mnt(old_nd.mnt, nd); + touch_namespace(current->namespace); /* if the mount is moved, it should no longer be expire * automatically */ @@ -877,6 +899,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) struct nameidata old_nd; /* delete from the namespace */ + touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; detach_mnt(mnt, &old_nd); @@ -1114,6 +1137,8 @@ int copy_namespace(int flags, struct task_struct *tsk) atomic_set(&new_ns->count, 1); init_rwsem(&new_ns->sem); INIT_LIST_HEAD(&new_ns->list); + init_waitqueue_head(&new_ns->poll); + new_ns->event = 0; down_write(&tsk->namespace->sem); /* First pass: copy the tree topology */ @@ -1377,6 +1402,7 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p detach_mnt(user_nd.mnt, &root_parent); attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ + touch_namespace(current->namespace); spin_unlock(&vfsmount_lock); chroot_fs_refs(&user_nd, &new_nd); security_sb_post_pivotroot(&user_nd, &new_nd); @@ -1413,6 +1439,8 @@ static void __init init_mount_tree(void) atomic_set(&namespace->count, 1); INIT_LIST_HEAD(&namespace->list); init_rwsem(&namespace->sem); + init_waitqueue_head(&namespace->poll); + namespace->event = 0; list_add(&mnt->mnt_list, &namespace->list); namespace->root = mnt; mnt->mnt_namespace = namespace; diff --git a/fs/proc/base.c b/fs/proc/base.c index a170450aadb1..634355e16986 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -70,6 +70,7 @@ #include #include #include +#include #include "internal.h" /* @@ -660,26 +661,38 @@ static struct file_operations proc_smaps_operations = { #endif extern struct seq_operations mounts_op; +struct proc_mounts { + struct seq_file m; + int event; +}; + static int mounts_open(struct inode *inode, struct file *file) { struct task_struct *task = proc_task(inode); - int ret = seq_open(file, &mounts_op); + struct namespace *namespace; + struct proc_mounts *p; + int ret = -EINVAL; - if (!ret) { - struct seq_file *m = file->private_data; - struct namespace *namespace; - task_lock(task); - namespace = task->namespace; - if (namespace) - get_namespace(namespace); - task_unlock(task); - - if (namespace) - m->private = namespace; - else { - seq_release(inode, file); - ret = -EINVAL; + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); + + if (namespace) { + ret = -ENOMEM; + p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); + if (p) { + file->private_data = &p->m; + ret = seq_open(file, &mounts_op); + if (!ret) { + p->m.private = namespace; + p->event = namespace->event; + return 0; + } + kfree(p); } + put_namespace(namespace); } return ret; } @@ -692,11 +705,30 @@ static int mounts_release(struct inode *inode, struct file *file) return seq_release(inode, file); } +static unsigned mounts_poll(struct file *file, poll_table *wait) +{ + struct proc_mounts *p = file->private_data; + struct namespace *ns = p->m.private; + unsigned res = 0; + + poll_wait(file, &ns->poll, wait); + + spin_lock(&vfsmount_lock); + if (p->event != ns->event) { + p->event = ns->event; + res = POLLERR; + } + spin_unlock(&vfsmount_lock); + + return res; +} + static struct file_operations proc_mounts_operations = { .open = mounts_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, + .poll = mounts_poll, }; #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 0e5a86f13b2f..6f0f25d64c38 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -10,6 +10,8 @@ struct namespace { struct vfsmount * root; struct list_head list; struct rw_semaphore sem; + wait_queue_head_t poll; + int event; }; extern int copy_namespace(int, struct task_struct *); -- cgit v1.2.3 From 390c684367de37e1c2f9005cf92f7a746c69fdd3 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:17:51 -0500 Subject: [PATCH] making namespace_sem global This removes the per-namespace semaphore in favor of a global semaphore. This can have an effect on namespace scalability. Signed-off-by: Miklos Szeredi Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 46 +++++++++++++++++++++++----------------------- include/linux/namespace.h | 1 - 2 files changed, 23 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 65f9c0ecc21c..4abee9ab009f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -46,6 +46,7 @@ static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; static kmem_cache_t *mnt_cache; +static struct rw_semaphore namespace_sem; static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { @@ -250,7 +251,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) struct list_head *p; loff_t l = *pos; - down_read(&n->sem); + down_read(&namespace_sem); list_for_each(p, &n->list) if (!l--) return list_entry(p, struct vfsmount, mnt_list); @@ -267,8 +268,7 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos) static void m_stop(struct seq_file *m, void *v) { - struct namespace *n = m->private; - up_read(&n->sem); + up_read(&namespace_sem); } static inline void mangle(struct seq_file *m, const char *s) @@ -487,7 +487,7 @@ static int do_umount(struct vfsmount *mnt, int flags) return retval; } - down_write(¤t->namespace->sem); + down_write(&namespace_sem); spin_lock(&vfsmount_lock); event++; @@ -500,7 +500,7 @@ static int do_umount(struct vfsmount *mnt, int flags) spin_unlock(&vfsmount_lock); if (retval) security_sb_umount_busy(mnt); - up_write(¤t->namespace->sem); + up_write(&namespace_sem); release_mounts(&umount_list); return retval; } @@ -678,7 +678,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (err) return err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); err = -EINVAL; if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) goto out; @@ -702,7 +702,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) } out: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); path_release(&old_nd); return err; } @@ -750,7 +750,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) if (err) return err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = -EINVAL; @@ -795,7 +795,7 @@ out2: out1: up(&nd->dentry->d_inode->i_sem); out: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); if (!err) path_release(&parent_nd); path_release(&old_nd); @@ -834,7 +834,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, { int err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); /* Something was mounted here while we slept */ while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; @@ -862,11 +862,11 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, list_add_tail(&newmnt->mnt_expire, fslist); spin_unlock(&vfsmount_lock); } - up_write(¤t->namespace->sem); + up_write(&namespace_sem); return 0; unlock: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); mntput(newmnt); return err; } @@ -958,9 +958,9 @@ void mark_mounts_for_expiry(struct list_head *mounts) get_namespace(namespace); spin_unlock(&vfsmount_lock); - down_write(&namespace->sem); + down_write(&namespace_sem); expire_mount(mnt, mounts, &umounts); - up_write(&namespace->sem); + up_write(&namespace_sem); release_mounts(&umounts); mntput(mnt); put_namespace(namespace); @@ -1127,17 +1127,16 @@ int copy_namespace(int flags, struct task_struct *tsk) goto out; atomic_set(&new_ns->count, 1); - init_rwsem(&new_ns->sem); INIT_LIST_HEAD(&new_ns->list); init_waitqueue_head(&new_ns->poll); new_ns->event = 0; - down_write(&tsk->namespace->sem); + down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, CL_EXPIRE); if (!new_ns->root) { - up_write(&tsk->namespace->sem); + up_write(&namespace_sem); kfree(new_ns); goto out; } @@ -1171,7 +1170,7 @@ int copy_namespace(int flags, struct task_struct *tsk) p = next_mnt(p, namespace->root); q = next_mnt(q, new_ns->root); } - up_write(&tsk->namespace->sem); + up_write(&namespace_sem); tsk->namespace = new_ns; @@ -1356,7 +1355,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, user_nd.mnt = mntget(current->fs->rootmnt); user_nd.dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); - down_write(¤t->namespace->sem); + down_write(&namespace_sem); down(&old_nd.dentry->d_inode->i_sem); error = -EINVAL; if (!check_mnt(user_nd.mnt)) @@ -1407,7 +1406,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, path_release(&parent_nd); out2: up(&old_nd.dentry->d_inode->i_sem); - up_write(¤t->namespace->sem); + up_write(&namespace_sem); path_release(&user_nd); path_release(&old_nd); out1: @@ -1434,7 +1433,6 @@ static void __init init_mount_tree(void) panic("Can't allocate initial namespace"); atomic_set(&namespace->count, 1); INIT_LIST_HEAD(&namespace->list); - init_rwsem(&namespace->sem); init_waitqueue_head(&namespace->poll); namespace->event = 0; list_add(&mnt->mnt_list, &namespace->list); @@ -1459,6 +1457,8 @@ void __init mnt_init(unsigned long mempages) unsigned int nr_hash; int i; + init_rwsem(&namespace_sem); + mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL); @@ -1507,11 +1507,11 @@ void __put_namespace(struct namespace *namespace) LIST_HEAD(umount_list); namespace->root = NULL; spin_unlock(&vfsmount_lock); - down_write(&namespace->sem); + down_write(&namespace_sem); spin_lock(&vfsmount_lock); umount_tree(root, &umount_list); spin_unlock(&vfsmount_lock); - up_write(&namespace->sem); + up_write(&namespace_sem); release_mounts(&umount_list); kfree(namespace); } diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 6f0f25d64c38..6731977c4c13 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -9,7 +9,6 @@ struct namespace { atomic_t count; struct vfsmount * root; struct list_head list; - struct rw_semaphore sem; wait_queue_head_t poll; int event; }; -- cgit v1.2.3 From 07b20889e3052c7e77d6a6a54e7e83446eb1ba84 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:07 -0500 Subject: [PATCH] beginning of the shared-subtree proper A private mount does not forward or receive propagation. This patch provides user the ability to convert any mount to private. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/Makefile | 2 +- fs/namespace.c | 24 ++++++++++++++++++++++++ fs/pnode.c | 17 +++++++++++++++++ fs/pnode.h | 14 ++++++++++++++ include/linux/fs.h | 1 + include/linux/mount.h | 10 +++++----- 6 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 fs/pnode.c create mode 100644 fs/pnode.h (limited to 'include') diff --git a/fs/Makefile b/fs/Makefile index 1972da186272..4c2655759078 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ - ioprio.o + ioprio.o pnode.o obj-$(CONFIG_INOTIFY) += inotify.o obj-$(CONFIG_EPOLL) += eventpoll.o diff --git a/fs/namespace.c b/fs/namespace.c index 4abee9ab009f..3782923d6d4d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -24,6 +24,7 @@ #include #include #include +#include "pnode.h" extern int __init init_rootfs(void); @@ -662,6 +663,27 @@ out_unlock: return err; } +/* + * recursively change the type of the mountpoint. + */ +static int do_change_type(struct nameidata *nd, int flag) +{ + struct vfsmount *m, *mnt = nd->mnt; + int recurse = flag & MS_REC; + int type = flag & ~MS_REC; + + if (nd->dentry != nd->mnt->mnt_root) + return -EINVAL; + + down_write(&namespace_sem); + spin_lock(&vfsmount_lock); + for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) + change_mnt_propagation(m, type); + spin_unlock(&vfsmount_lock); + up_write(&namespace_sem); + return 0; +} + /* * do loopback mount. */ @@ -1091,6 +1113,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); + else if (flags & MS_PRIVATE) + retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); else diff --git a/fs/pnode.c b/fs/pnode.c new file mode 100644 index 000000000000..aaa0dffda12a --- /dev/null +++ b/fs/pnode.c @@ -0,0 +1,17 @@ +/* + * linux/fs/pnode.c + * + * (C) Copyright IBM Corporation 2005. + * Released under GPL v2. + * Author : Ram Pai (linuxram@us.ibm.com) + * + */ +#include +#include +#include +#include "pnode.h" + +void change_mnt_propagation(struct vfsmount *mnt, int type) +{ + mnt->mnt_flags &= ~MNT_PNODE_MASK; +} diff --git a/fs/pnode.h b/fs/pnode.h new file mode 100644 index 000000000000..33549a3a74eb --- /dev/null +++ b/fs/pnode.h @@ -0,0 +1,14 @@ +/* + * linux/fs/pnode.h + * + * (C) Copyright IBM Corporation 2005. + * Released under GPL v2. + * + */ +#ifndef _LINUX_PNODE_H +#define _LINUX_PNODE_H + +#include +#include +void change_mnt_propagation(struct vfsmount *, int); +#endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 9a593ef262ef..6c431086abb3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -104,6 +104,7 @@ extern int dir_notify_enable; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 +#define MS_PRIVATE (1<<18) /* change to private */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index ffb0b5089880..8eadd3b65899 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -17,12 +17,12 @@ #include #include -#define MNT_NOSUID 1 -#define MNT_NODEV 2 -#define MNT_NOEXEC 4 +#define MNT_NOSUID 0x01 +#define MNT_NODEV 0x02 +#define MNT_NOEXEC 0x04 +#define MNT_PNODE_MASK 0x30 /* propogation flag mask */ -struct vfsmount -{ +struct vfsmount { struct list_head mnt_hash; struct vfsmount *mnt_parent; /* fs we are mounted on */ struct dentry *mnt_mountpoint; /* dentry of mountpoint */ -- cgit v1.2.3 From 03e06e68ff76294e53ffa898cb844d2a997b043e Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:33 -0500 Subject: [PATCH] introduce shared mounts This creates shared mounts. A shared mount when bind-mounted to some mountpoint, propagates mount/umount events to each other. All the shared mounts that propagate events to each other belong to the same peer-group. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 3 ++- fs/pnode.c | 13 ++++++++++++- fs/pnode.h | 4 ++++ include/linux/fs.h | 1 + include/linux/mount.h | 2 ++ 5 files changed, 21 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 3782923d6d4d..f6861a5487df 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -68,6 +68,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); + INIT_LIST_HEAD(&mnt->mnt_share); if (name) { int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); @@ -1113,7 +1114,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & MS_PRIVATE) + else if (flags & (MS_SHARED | MS_PRIVATE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index aaa0dffda12a..1e22165ea41f 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -11,7 +11,18 @@ #include #include "pnode.h" +/* return the next shared peer mount of @p */ +static inline struct vfsmount *next_peer(struct vfsmount *p) +{ + return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); +} + void change_mnt_propagation(struct vfsmount *mnt, int type) { - mnt->mnt_flags &= ~MNT_PNODE_MASK; + if (type == MS_SHARED) { + mnt->mnt_flags |= MNT_SHARED; + } else { + list_del_init(&mnt->mnt_share); + mnt->mnt_flags &= ~MNT_PNODE_MASK; + } } diff --git a/fs/pnode.h b/fs/pnode.h index 33549a3a74eb..ab1bdaee4e08 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -10,5 +10,9 @@ #include #include + +#define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) + void change_mnt_propagation(struct vfsmount *, int); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 6c431086abb3..551fba303cf8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -105,6 +105,7 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_PRIVATE (1<<18) /* change to private */ +#define MS_SHARED (1<<20) /* change to shared */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index 8eadd3b65899..2582559718fc 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -20,6 +20,7 @@ #define MNT_NOSUID 0x01 #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 +#define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */ struct vfsmount { @@ -36,6 +37,7 @@ struct vfsmount { char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ + struct list_head mnt_share; /* circular list of shared mounts */ struct namespace *mnt_namespace; /* containing namespace */ int mnt_pinned; }; -- cgit v1.2.3 From b90fa9ae8f51f098ee480bbaabd6867992e9fc58 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:50 -0500 Subject: [PATCH] shared mount handling: bind and rbind Implement handling of MS_BIND in presense of shared mounts (see Documentation/sharedsubtree.txt in the end of patch series for detailed description). Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 126 ++++++++++++++++++++++++++++++++++++++++++++--------- fs/pnode.c | 81 +++++++++++++++++++++++++++++++++- fs/pnode.h | 14 ++++++ include/linux/fs.h | 5 +++ 4 files changed, 204 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index f6861a5487df..9f5a084b239f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -28,8 +28,6 @@ extern int __init init_rootfs(void); -#define CL_EXPIRE 0x01 - #ifdef CONFIG_SYSFS extern int __init sysfs_init(void); #else @@ -145,13 +143,43 @@ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) old_nd->dentry->d_mounted--; } +void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, + struct vfsmount *child_mnt) +{ + child_mnt->mnt_parent = mntget(mnt); + child_mnt->mnt_mountpoint = dget(dentry); + dentry->d_mounted++; +} + static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); - list_add(&mnt->mnt_hash, mount_hashtable + hash(nd->mnt, nd->dentry)); + mnt_set_mountpoint(nd->mnt, nd->dentry, mnt); + list_add_tail(&mnt->mnt_hash, mount_hashtable + + hash(nd->mnt, nd->dentry)); list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; +} + +/* + * the caller must hold vfsmount_lock + */ +static void commit_tree(struct vfsmount *mnt) +{ + struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *m; + LIST_HEAD(head); + struct namespace *n = parent->mnt_namespace; + + BUG_ON(parent == mnt); + + list_add_tail(&head, &mnt->mnt_list); + list_for_each_entry(m, &head, mnt_list) + m->mnt_namespace = n; + list_splice(&head, n->list.prev); + + list_add_tail(&mnt->mnt_hash, mount_hashtable + + hash(parent, mnt->mnt_mountpoint)); + list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); + touch_namespace(n); } static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) @@ -183,7 +211,11 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - mnt->mnt_namespace = current->namespace; + + if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) + list_add(&mnt->mnt_share, &old->mnt_share); + if (flag & CL_MAKE_SHARED) + set_mnt_shared(mnt); /* stick the duplicate mount on the same expiry list * as the original if that was on one */ @@ -379,7 +411,7 @@ int may_umount(struct vfsmount *mnt) EXPORT_SYMBOL(may_umount); -static void release_mounts(struct list_head *head) +void release_mounts(struct list_head *head) { struct vfsmount *mnt; while(!list_empty(head)) { @@ -401,7 +433,7 @@ static void release_mounts(struct list_head *head) } } -static void umount_tree(struct vfsmount *mnt, struct list_head *kill) +void umount_tree(struct vfsmount *mnt, struct list_head *kill) { struct vfsmount *p; @@ -581,7 +613,7 @@ static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) } } -static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, +struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { struct vfsmount *res, *p, *q, *r, *s; @@ -626,6 +658,67 @@ Enomem: return NULL; } +/* + * @source_mnt : mount tree to be attached + * @nd : place the mount tree @source_mnt is attached + * + * NOTE: in the table below explains the semantics when a source mount + * of a given type is attached to a destination mount of a given type. + * --------------------------------------------- + * | BIND MOUNT OPERATION | + * |******************************************** + * | source-->| shared | private | + * | dest | | | + * | | | | | + * | v | | | + * |******************************************** + * | shared | shared (++) | shared (+) | + * | | | | + * |non-shared| shared (+) | private | + * ********************************************* + * A bind operation clones the source mount and mounts the clone on the + * destination mount. + * + * (++) the cloned mount is propagated to all the mounts in the propagation + * tree of the destination mount and the cloned mount is added to + * the peer group of the source mount. + * (+) the cloned mount is created under the destination mount and is marked + * as shared. The cloned mount is added to the peer group of the source + * mount. + * + * if the source mount is a tree, the operations explained above is + * applied to each mount in the tree. + * Must be called without spinlocks held, since this function can sleep + * in allocations. + */ +static int attach_recursive_mnt(struct vfsmount *source_mnt, + struct nameidata *nd) +{ + LIST_HEAD(tree_list); + struct vfsmount *dest_mnt = nd->mnt; + struct dentry *dest_dentry = nd->dentry; + struct vfsmount *child, *p; + + if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) + return -EINVAL; + + if (IS_MNT_SHARED(dest_mnt)) { + for (p = source_mnt; p; p = next_mnt(p, source_mnt)) + set_mnt_shared(p); + } + + spin_lock(&vfsmount_lock); + mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); + commit_tree(source_mnt); + + list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { + list_del_init(&child->mnt_hash); + commit_tree(child); + } + spin_unlock(&vfsmount_lock); + return 0; +} + static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) { int err; @@ -646,17 +739,8 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) goto out_unlock; err = -ENOENT; - spin_lock(&vfsmount_lock); - if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) { - struct list_head head; - - attach_mnt(mnt, nd); - list_add_tail(&head, &mnt->mnt_list); - list_splice(&head, current->namespace->list.prev); - err = 0; - touch_namespace(current->namespace); - } - spin_unlock(&vfsmount_lock); + if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) + err = attach_recursive_mnt(mnt, nd); out_unlock: up(&nd->dentry->d_inode->i_sem); if (!err) diff --git a/fs/pnode.c b/fs/pnode.c index 1e22165ea41f..2d572b88e6f6 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -20,9 +20,88 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { - mnt->mnt_flags |= MNT_SHARED; + set_mnt_shared(mnt); } else { list_del_init(&mnt->mnt_share); mnt->mnt_flags &= ~MNT_PNODE_MASK; } } + +/* + * get the next mount in the propagation tree. + * @m: the mount seen last + * @origin: the original mount from where the tree walk initiated + */ +static struct vfsmount *propagation_next(struct vfsmount *m, + struct vfsmount *origin) +{ + m = next_peer(m); + if (m == origin) + return NULL; + return m; +} + +/* + * mount 'source_mnt' under the destination 'dest_mnt' at + * dentry 'dest_dentry'. And propagate that mount to + * all the peer and slave mounts of 'dest_mnt'. + * Link all the new mounts into a propagation tree headed at + * source_mnt. Also link all the new mounts using ->mnt_list + * headed at source_mnt's ->mnt_list + * + * @dest_mnt: destination mount. + * @dest_dentry: destination dentry. + * @source_mnt: source mount. + * @tree_list : list of heads of trees to be attached. + */ +int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, + struct vfsmount *source_mnt, struct list_head *tree_list) +{ + struct vfsmount *m, *child; + int ret = 0; + struct vfsmount *prev_dest_mnt = dest_mnt; + struct vfsmount *prev_src_mnt = source_mnt; + LIST_HEAD(tmp_list); + LIST_HEAD(umount_list); + + for (m = propagation_next(dest_mnt, dest_mnt); m; + m = propagation_next(m, dest_mnt)) { + int type = CL_PROPAGATION; + + if (IS_MNT_NEW(m)) + continue; + + if (IS_MNT_SHARED(m)) + type |= CL_MAKE_SHARED; + + if (!(child = copy_tree(source_mnt, source_mnt->mnt_root, + type))) { + ret = -ENOMEM; + list_splice(tree_list, tmp_list.prev); + goto out; + } + + if (is_subdir(dest_dentry, m->mnt_root)) { + mnt_set_mountpoint(m, dest_dentry, child); + list_add_tail(&child->mnt_hash, tree_list); + } else { + /* + * This can happen if the parent mount was bind mounted + * on some subdirectory of a shared/slave mount. + */ + list_add_tail(&child->mnt_hash, &tmp_list); + } + prev_dest_mnt = m; + prev_src_mnt = child; + } +out: + spin_lock(&vfsmount_lock); + while (!list_empty(&tmp_list)) { + child = list_entry(tmp_list.next, struct vfsmount, mnt_hash); + list_del_init(&child->mnt_hash); + umount_tree(child, &umount_list); + } + spin_unlock(&vfsmount_lock); + release_mounts(&umount_list); + return ret; +} diff --git a/fs/pnode.h b/fs/pnode.h index ab1bdaee4e08..c62c72fad212 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,7 +12,21 @@ #include #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) +#define CL_EXPIRE 0x01 +#define CL_COPY_ALL 0x04 +#define CL_MAKE_SHARED 0x08 +#define CL_PROPAGATION 0x10 + +static inline void set_mnt_shared(struct vfsmount *mnt) +{ + mnt->mnt_flags &= ~MNT_PNODE_MASK; + mnt->mnt_flags |= MNT_SHARED; +} + void change_mnt_propagation(struct vfsmount *, int); +int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, + struct list_head *); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 551fba303cf8..5e188b773e9c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1251,7 +1251,12 @@ extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount_tree(struct vfsmount *); extern int may_umount(struct vfsmount *); +extern void umount_tree(struct vfsmount *, struct list_head *); +extern void release_mounts(struct list_head *); extern long do_mount(char *, char *, char *, unsigned long, void *); +extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); +extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, + struct vfsmount *); extern int vfs_statfs(struct super_block *, struct kstatfs *); -- cgit v1.2.3 From a05964f3917c7c55368c229d7985f8e7c9977e97 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:17 -0500 Subject: [PATCH] shared mounts handling: umount An unmount of a mount creates a umount event on the parent. If the parent is a shared mount, it gets propagated to all mounts in the peer group. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 56 +++++++++++++++++++++----------- fs/pnode.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++- fs/pnode.h | 2 ++ include/linux/dcache.h | 1 + include/linux/fs.h | 2 +- 5 files changed, 128 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 1487982dbc24..4b1af01c2fb4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -86,31 +86,44 @@ void free_vfsmnt(struct vfsmount *mnt) } /* - * Now, lookup_mnt increments the ref count before returning - * the vfsmount struct. + * find the first or last mount at @dentry on vfsmount @mnt depending on + * @dir. If @dir is set return the first mount else return the last mount. */ -struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, + int dir) { struct list_head *head = mount_hashtable + hash(mnt, dentry); struct list_head *tmp = head; struct vfsmount *p, *found = NULL; - spin_lock(&vfsmount_lock); for (;;) { - tmp = tmp->next; + tmp = dir ? tmp->next : tmp->prev; p = NULL; if (tmp == head) break; p = list_entry(tmp, struct vfsmount, mnt_hash); if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) { - found = mntget(p); + found = p; break; } } - spin_unlock(&vfsmount_lock); return found; } +/* + * lookup_mnt increments the ref count before returning + * the vfsmount struct. + */ +struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +{ + struct vfsmount *child_mnt; + spin_lock(&vfsmount_lock); + if ((child_mnt = __lookup_mnt(mnt, dentry, 1))) + mntget(child_mnt); + spin_unlock(&vfsmount_lock); + return child_mnt; +} + static inline int check_mnt(struct vfsmount *mnt) { return mnt->mnt_namespace == current->namespace; @@ -404,9 +417,12 @@ EXPORT_SYMBOL(may_umount_tree); */ int may_umount(struct vfsmount *mnt) { - if (atomic_read(&mnt->mnt_count) > 2) - return -EBUSY; - return 0; + int ret = 0; + spin_lock(&vfsmount_lock); + if (propagate_mount_busy(mnt, 2)) + ret = -EBUSY; + spin_unlock(&vfsmount_lock); + return ret; } EXPORT_SYMBOL(may_umount); @@ -433,7 +449,7 @@ void release_mounts(struct list_head *head) } } -void umount_tree(struct vfsmount *mnt, struct list_head *kill) +void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) { struct vfsmount *p; @@ -442,6 +458,9 @@ void umount_tree(struct vfsmount *mnt, struct list_head *kill) list_add(&p->mnt_hash, kill); } + if (propagate) + propagate_umount(kill); + list_for_each_entry(p, kill, mnt_hash) { list_del_init(&p->mnt_expire); list_del_init(&p->mnt_list); @@ -450,6 +469,7 @@ void umount_tree(struct vfsmount *mnt, struct list_head *kill) list_del_init(&p->mnt_child); if (p->mnt_parent != p) mnt->mnt_mountpoint->d_mounted--; + change_mnt_propagation(p, MS_PRIVATE); } } @@ -526,9 +546,9 @@ static int do_umount(struct vfsmount *mnt, int flags) event++; retval = -EBUSY; - if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { + if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { if (!list_empty(&mnt->mnt_list)) - umount_tree(mnt, &umount_list); + umount_tree(mnt, 1, &umount_list); retval = 0; } spin_unlock(&vfsmount_lock); @@ -651,7 +671,7 @@ Enomem: if (res) { LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(res, &umount_list); + umount_tree(res, 0, &umount_list); spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -827,7 +847,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (err) { LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(mnt, &umount_list); + umount_tree(mnt, 0, &umount_list); spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -1023,12 +1043,12 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, * Check that it is still dead: the count should now be 2 - as * contributed by the vfsmount parent and the mntget above */ - if (atomic_read(&mnt->mnt_count) == 2) { + if (!propagate_mount_busy(mnt, 2)) { /* delete from the namespace */ touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; - umount_tree(mnt, umounts); + umount_tree(mnt, 1, umounts); spin_unlock(&vfsmount_lock); } else { /* @@ -1647,7 +1667,7 @@ void __put_namespace(struct namespace *namespace) spin_unlock(&vfsmount_lock); down_write(&namespace_sem); spin_lock(&vfsmount_lock); - umount_tree(root, &umount_list); + umount_tree(root, 0, &umount_list); spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); diff --git a/fs/pnode.c b/fs/pnode.c index 2d572b88e6f6..7bc942d047cd 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -99,9 +99,94 @@ out: while (!list_empty(&tmp_list)) { child = list_entry(tmp_list.next, struct vfsmount, mnt_hash); list_del_init(&child->mnt_hash); - umount_tree(child, &umount_list); + umount_tree(child, 0, &umount_list); } spin_unlock(&vfsmount_lock); release_mounts(&umount_list); return ret; } + +/* + * return true if the refcount is greater than count + */ +static inline int do_refcount_check(struct vfsmount *mnt, int count) +{ + int mycount = atomic_read(&mnt->mnt_count); + return (mycount > count); +} + +/* + * check if the mount 'mnt' can be unmounted successfully. + * @mnt: the mount to be checked for unmount + * NOTE: unmounting 'mnt' would naturally propagate to all + * other mounts its parent propagates to. + * Check if any of these mounts that **do not have submounts** + * have more references than 'refcnt'. If so return busy. + */ +int propagate_mount_busy(struct vfsmount *mnt, int refcnt) +{ + struct vfsmount *m, *child; + struct vfsmount *parent = mnt->mnt_parent; + int ret = 0; + + if (mnt == parent) + return do_refcount_check(mnt, refcnt); + + /* + * quickly check if the current mount can be unmounted. + * If not, we don't have to go checking for all other + * mounts + */ + if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt)) + return 1; + + for (m = propagation_next(parent, parent); m; + m = propagation_next(m, parent)) { + child = __lookup_mnt(m, mnt->mnt_mountpoint, 0); + if (child && list_empty(&child->mnt_mounts) && + (ret = do_refcount_check(child, 1))) + break; + } + return ret; +} + +/* + * NOTE: unmounting 'mnt' naturally propagates to all other mounts its + * parent propagates to. + */ +static void __propagate_umount(struct vfsmount *mnt) +{ + struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *m; + + BUG_ON(parent == mnt); + + for (m = propagation_next(parent, parent); m; + m = propagation_next(m, parent)) { + + struct vfsmount *child = __lookup_mnt(m, + mnt->mnt_mountpoint, 0); + /* + * umount the child only if the child has no + * other children + */ + if (child && list_empty(&child->mnt_mounts)) { + list_del(&child->mnt_hash); + list_add_tail(&child->mnt_hash, &mnt->mnt_hash); + } + } +} + +/* + * collect all mounts that receive propagation from the mount in @list, + * and return these additional mounts in the same list. + * @list: the list of mounts to be unmounted. + */ +int propagate_umount(struct list_head *list) +{ + struct vfsmount *mnt; + + list_for_each_entry(mnt, list, mnt_hash) + __propagate_umount(mnt); + return 0; +} diff --git a/fs/pnode.h b/fs/pnode.h index c62c72fad212..9b88ba06794a 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -29,4 +29,6 @@ static inline void set_mnt_shared(struct vfsmount *mnt) void change_mnt_propagation(struct vfsmount *, int); int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, struct list_head *); +int propagate_umount(struct list_head *); +int propagate_mount_busy(struct vfsmount *, int); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index ab04b4f9b0db..46a2ba617595 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -329,6 +329,7 @@ static inline int d_mountpoint(struct dentry *dentry) } extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *); +extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); extern struct dentry *lookup_create(struct nameidata *nd, int is_dir); extern int sysctl_vfs_cache_pressure; diff --git a/include/linux/fs.h b/include/linux/fs.h index 5e188b773e9c..8bdb504be73b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1251,7 +1251,7 @@ extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount_tree(struct vfsmount *); extern int may_umount(struct vfsmount *); -extern void umount_tree(struct vfsmount *, struct list_head *); +extern void umount_tree(struct vfsmount *, int, struct list_head *); extern void release_mounts(struct list_head *); extern long do_mount(char *, char *, char *, unsigned long, void *); extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); -- cgit v1.2.3 From a58b0eb8e64b78d9315a5491955e78b1391d42e5 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:48 -0500 Subject: [PATCH] introduce slave mounts A slave mount always has a master mount from which it receives mount/umount events. Unlike shared mount the event propagation does not flow from the slave mount to the master. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 4 +++- fs/pnode.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++--- fs/pnode.h | 2 ++ include/linux/fs.h | 1 + include/linux/mount.h | 3 +++ 5 files changed, 60 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 4b1af01c2fb4..46f99bc585bd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -67,6 +67,8 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); INIT_LIST_HEAD(&mnt->mnt_share); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + INIT_LIST_HEAD(&mnt->mnt_slave); if (name) { int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); @@ -1243,7 +1245,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index 7bc942d047cd..f73eba24f1d1 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -17,13 +17,61 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); } +static int do_make_slave(struct vfsmount *mnt) +{ + struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master; + struct vfsmount *slave_mnt; + + /* + * slave 'mnt' to a peer mount that has the + * same root dentry. If none is available than + * slave it to anything that is available. + */ + while ((peer_mnt = next_peer(peer_mnt)) != mnt && + peer_mnt->mnt_root != mnt->mnt_root) ; + + if (peer_mnt == mnt) { + peer_mnt = next_peer(mnt); + if (peer_mnt == mnt) + peer_mnt = NULL; + } + list_del_init(&mnt->mnt_share); + + if (peer_mnt) + master = peer_mnt; + + if (master) { + list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) + slave_mnt->mnt_master = master; + list_del(&mnt->mnt_slave); + list_add(&mnt->mnt_slave, &master->mnt_slave_list); + list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + } else { + struct list_head *p = &mnt->mnt_slave_list; + while (!list_empty(p)) { + slave_mnt = list_entry(p->next, + struct vfsmount, mnt_slave); + list_del_init(&slave_mnt->mnt_slave); + slave_mnt->mnt_master = NULL; + } + } + mnt->mnt_master = master; + CLEAR_MNT_SHARED(mnt); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + return 0; +} + void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { set_mnt_shared(mnt); - } else { - list_del_init(&mnt->mnt_share); - mnt->mnt_flags &= ~MNT_PNODE_MASK; + return; + } + do_make_slave(mnt); + if (type != MS_SLAVE) { + list_del_init(&mnt->mnt_slave); + mnt->mnt_master = NULL; } } diff --git a/fs/pnode.h b/fs/pnode.h index 9b88ba06794a..b59f0e9fe6b1 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,10 +12,12 @@ #include #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define IS_MNT_SLAVE(mnt) (mnt->mnt_master) #define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) #define CL_EXPIRE 0x01 +#define CL_SLAVE 0x02 #define CL_COPY_ALL 0x04 #define CL_MAKE_SHARED 0x08 #define CL_PROPAGATION 0x10 diff --git a/include/linux/fs.h b/include/linux/fs.h index 8bdb504be73b..eef66f54c017 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -105,6 +105,7 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_PRIVATE (1<<18) /* change to private */ +#define MS_SLAVE (1<<19) /* change to slave */ #define MS_SHARED (1<<20) /* change to shared */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) diff --git a/include/linux/mount.h b/include/linux/mount.h index 2582559718fc..7e133ae2a94f 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -38,6 +38,9 @@ struct vfsmount { struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct list_head mnt_share; /* circular list of shared mounts */ + struct list_head mnt_slave_list;/* list of slave mounts */ + struct list_head mnt_slave; /* slave list entry */ + struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ struct namespace *mnt_namespace; /* containing namespace */ int mnt_pinned; }; -- cgit v1.2.3 From 9676f0c6389b62bd6b24d77d4b3abdbcfa32d0f2 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:21:20 -0500 Subject: [PATCH] unbindable mounts An unbindable mount does not forward or receive propagation. Also unbindable mount disallows bind mounts. The semantics is as follows. Bind semantics: It is invalid to bind mount an unbindable mount. Move semantics: It is invalid to move an unbindable mount under shared mount. Clone-namespace semantics: If a mount is unbindable in the parent namespace, the corresponding cloned mount in the child namespace becomes unbindable too. Note: there is subtle difference, unbindable mounts cannot be bind mounted but can be cloned during clone-namespace. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 88 ++++++++++++++++++++++++++++++++++++--------------- fs/pnode.c | 2 ++ fs/pnode.h | 1 + include/linux/fs.h | 1 + include/linux/mount.h | 1 + 5 files changed, 67 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 089670363704..caa9187f67e5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -213,6 +213,16 @@ static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) return list_entry(next, struct vfsmount, mnt_child); } +static struct vfsmount *skip_mnt_tree(struct vfsmount *p) +{ + struct list_head *prev = p->mnt_mounts.prev; + while (prev != &p->mnt_mounts) { + p = list_entry(prev, struct vfsmount, mnt_child); + prev = p->mnt_mounts.prev; + } + return p; +} + static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { @@ -650,6 +660,9 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *res, *p, *q, *r, *s; struct nameidata nd; + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) + return NULL; + res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; @@ -661,6 +674,10 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, continue; for (s = r; s; s = next_mnt(s, r)) { + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) { + s = skip_mnt_tree(s); + continue; + } while (p != s->mnt_parent) { p = p->mnt_parent; q = q->mnt_parent; @@ -698,18 +715,18 @@ Enomem: * * NOTE: in the table below explains the semantics when a source mount * of a given type is attached to a destination mount of a given type. - * ------------------------------------------------------------- - * | BIND MOUNT OPERATION | - * |************************************************************* - * | source-->| shared | private | slave | - * | dest | | | | - * | | | | | | - * | v | | | | - * |************************************************************* - * | shared | shared (++) | shared (+) | shared(+++)| - * | | | | | - * |non-shared| shared (+) | private | slave (*) | - * ************************************************************** + * --------------------------------------------------------------------------- + * | BIND MOUNT OPERATION | + * |************************************************************************** + * | source-->| shared | private | slave | unbindable | + * | dest | | | | | + * | | | | | | | + * | v | | | | | + * |************************************************************************** + * | shared | shared (++) | shared (+) | shared(+++)| invalid | + * | | | | | | + * |non-shared| shared (+) | private | slave (*) | invalid | + * *************************************************************************** * A bind operation clones the source mount and mounts the clone on the * destination mount. * @@ -726,18 +743,18 @@ Enomem: * (*) the cloned mount is made a slave of the same master as that of the * source mount. * - * -------------------------------------------------------------- - * | MOVE MOUNT OPERATION | - * |************************************************************* - * | source-->| shared | private | slave | - * | dest | | | | - * | | | | | | - * | v | | | | - * |************************************************************* - * | shared | shared (+) | shared (+) | shared(+++) | - * | | | | | - * |non-shared| shared (+*) | private | slave (*) | - * ************************************************************** + * --------------------------------------------------------------------------- + * | MOVE MOUNT OPERATION | + * |************************************************************************** + * | source-->| shared | private | slave | unbindable | + * | dest | | | | | + * | | | | | | | + * | v | | | | | + * |************************************************************************** + * | shared | shared (+) | shared (+) | shared(+++) | invalid | + * | | | | | | + * |non-shared| shared (+*) | private | slave (*) | unbindable | + * *************************************************************************** * * (+) the mount is moved to the destination. And is then propagated to * all the mounts in the propagation tree of the destination mount. @@ -854,6 +871,9 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) down_write(&namespace_sem); err = -EINVAL; + if (IS_MNT_UNBINDABLE(old_nd.mnt)) + goto out; + if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) goto out; @@ -911,6 +931,16 @@ static int do_remount(struct nameidata *nd, int flags, int mnt_flags, return err; } +static inline int tree_contains_unbindable(struct vfsmount *mnt) +{ + struct vfsmount *p; + for (p = mnt; p; p = next_mnt(p, mnt)) { + if (IS_MNT_UNBINDABLE(p)) + return 1; + } + return 0; +} + static int do_move_mount(struct nameidata *nd, char *old_name) { struct nameidata old_nd, parent_nd; @@ -954,6 +984,12 @@ static int do_move_mount(struct nameidata *nd, char *old_name) */ if (old_nd.mnt->mnt_parent && IS_MNT_SHARED(old_nd.mnt->mnt_parent)) goto out1; + /* + * Don't move a mount tree containing unbindable mounts to a destination + * mount which is shared. + */ + if (IS_MNT_SHARED(nd->mnt) && tree_contains_unbindable(old_nd.mnt)) + goto out1; err = -ELOOP; for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) if (p == old_nd.mnt) @@ -1266,7 +1302,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); @@ -1311,7 +1347,7 @@ int copy_namespace(int flags, struct task_struct *tsk) down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, - CL_EXPIRE); + CL_COPY_ALL | CL_EXPIRE); if (!new_ns->root) { up_write(&namespace_sem); kfree(new_ns); diff --git a/fs/pnode.c b/fs/pnode.c index 3e266c5a3071..aeeec8ba8dd2 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -82,6 +82,8 @@ void change_mnt_propagation(struct vfsmount *mnt, int type) if (type != MS_SLAVE) { list_del_init(&mnt->mnt_slave); mnt->mnt_master = NULL; + if (type == MS_UNBINDABLE) + mnt->mnt_flags |= MNT_UNBINDABLE; } } diff --git a/fs/pnode.h b/fs/pnode.h index b59f0e9fe6b1..020e1bb60fdb 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -15,6 +15,7 @@ #define IS_MNT_SLAVE(mnt) (mnt->mnt_master) #define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) +#define IS_MNT_UNBINDABLE(mnt) (mnt->mnt_flags & MNT_UNBINDABLE) #define CL_EXPIRE 0x01 #define CL_SLAVE 0x02 diff --git a/include/linux/fs.h b/include/linux/fs.h index eef66f54c017..1b5f502a4b8f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -104,6 +104,7 @@ extern int dir_notify_enable; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 +#define MS_UNBINDABLE (1<<17) /* change to unbindable */ #define MS_PRIVATE (1<<18) /* change to private */ #define MS_SLAVE (1<<19) /* change to slave */ #define MS_SHARED (1<<20) /* change to shared */ diff --git a/include/linux/mount.h b/include/linux/mount.h index 7e133ae2a94f..dd4e83eba933 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -21,6 +21,7 @@ #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 #define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ +#define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */ struct vfsmount { -- cgit v1.2.3 From 48888cc6120ff945675ef79a3ba2955afa0f5124 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 5 Nov 2005 20:01:47 +0100 Subject: [PATCH] kill include/linux/eeprom.h This patch kills include/linux/eeprom.h . Rationale: - it was only used by one single driver - even this driver didn't do anything useful with it - most of this file are non-inline and non-static functions (sic) This removes include/linux/eeprom.h and cleans drivers/net/ns83820.c up. If you think eeprom.h should be used more extensively, please consider: - the code has to be moved from the header file to a .c file - the currently empty write function has to be implemented - ns83820.c or any other driver should actually use it Noone did any of these during the more than 3 years eeprom.h already exists... Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/ns83820.c | 13 +---- include/linux/eeprom.h | 136 ------------------------------------------------- 2 files changed, 2 insertions(+), 147 deletions(-) delete mode 100644 include/linux/eeprom.h (limited to 'include') diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index a3c3fc9c0d8a..f857ae94d261 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -110,7 +110,6 @@ #include #include /* for iph */ #include /* for IPPROTO_... */ -#include #include #include #include @@ -445,7 +444,6 @@ struct ns83820 { u32 MEAR_cache; u32 IMR_cache; - struct eeprom ee; unsigned linkstate; @@ -1558,15 +1556,13 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac) unsigned i; for (i=0; i<3; i++) { u32 data; -#if 0 /* I've left this in as an example of how to use eeprom.h */ - data = eeprom_readw(&dev->ee, 0xa + 2 - i); -#else + /* Read from the perfect match memory: this is loaded by * the chip from the EEPROM via the EELOAD self test. */ writel(i*2, dev->base + RFCR); data = readl(dev->base + RFDR); -#endif + *mac++ = data; *mac++ = data >> 8; } @@ -1851,8 +1847,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ spin_lock_init(&dev->misc_lock); dev->pci_dev = pci_dev; - dev->ee.cache = &dev->MEAR_cache; - dev->ee.lock = &dev->misc_lock; SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); @@ -1887,9 +1881,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ dev->IMR_cache = 0; - setup_ee_mem_bitbanger(&dev->ee, dev->base + MEAR, 3, 2, 1, 0, - 0); - err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, DRV_NAME, ndev); if (err) { diff --git a/include/linux/eeprom.h b/include/linux/eeprom.h deleted file mode 100644 index 38afd9da1dfe..000000000000 --- a/include/linux/eeprom.h +++ /dev/null @@ -1,136 +0,0 @@ -/* credit winbond-840.c - */ -#include -struct eeprom_ops { - void (*set_cs)(void *ee); - void (*clear_cs)(void *ee); -}; - -#define EEPOL_EEDI 0x01 -#define EEPOL_EEDO 0x02 -#define EEPOL_EECLK 0x04 -#define EEPOL_EESEL 0x08 - -struct eeprom { - void *dev; - struct eeprom_ops *ops; - - void __iomem * addr; - - unsigned ee_addr_bits; - - unsigned eesel; - unsigned eeclk; - unsigned eedo; - unsigned eedi; - unsigned polarity; - unsigned ee_state; - - spinlock_t *lock; - u32 *cache; -}; - - -u8 eeprom_readb(struct eeprom *ee, unsigned address); -void eeprom_read(struct eeprom *ee, unsigned address, u8 *bytes, - unsigned count); -void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data); -void eeprom_write(struct eeprom *ee, unsigned address, u8 *bytes, - unsigned count); - -/* The EEPROM commands include the alway-set leading bit. */ -enum EEPROM_Cmds { - EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), -}; - -void setup_ee_mem_bitbanger(struct eeprom *ee, void __iomem *memaddr, int eesel_bit, int eeclk_bit, int eedo_bit, int eedi_bit, unsigned polarity) -{ - ee->addr = memaddr; - ee->eesel = 1 << eesel_bit; - ee->eeclk = 1 << eeclk_bit; - ee->eedo = 1 << eedo_bit; - ee->eedi = 1 << eedi_bit; - - ee->polarity = polarity; - - *ee->cache = readl(ee->addr); -} - -/* foo. put this in a .c file */ -static inline void eeprom_update(struct eeprom *ee, u32 mask, int pol) -{ - unsigned long flags; - u32 data; - - spin_lock_irqsave(ee->lock, flags); - data = *ee->cache; - - data &= ~mask; - if (pol) - data |= mask; - - *ee->cache = data; -//printk("update: %08x\n", data); - writel(data, ee->addr); - spin_unlock_irqrestore(ee->lock, flags); -} - -void eeprom_clk_lo(struct eeprom *ee) -{ - int pol = !!(ee->polarity & EEPOL_EECLK); - - eeprom_update(ee, ee->eeclk, pol); - udelay(2); -} - -void eeprom_clk_hi(struct eeprom *ee) -{ - int pol = !!(ee->polarity & EEPOL_EECLK); - - eeprom_update(ee, ee->eeclk, !pol); - udelay(2); -} - -void eeprom_send_addr(struct eeprom *ee, unsigned address) -{ - int pol = !!(ee->polarity & EEPOL_EEDI); - unsigned i; - address |= 6 << 6; - - /* Shift the read command bits out. */ - for (i=0; i<11; i++) { - eeprom_update(ee, ee->eedi, ((address >> 10) & 1) ^ pol); - address <<= 1; - eeprom_clk_hi(ee); - eeprom_clk_lo(ee); - } - eeprom_update(ee, ee->eedi, pol); -} - -u16 eeprom_readw(struct eeprom *ee, unsigned address) -{ - unsigned i; - u16 res = 0; - - eeprom_clk_lo(ee); - eeprom_update(ee, ee->eesel, 1 ^ !!(ee->polarity & EEPOL_EESEL)); - eeprom_send_addr(ee, address); - - for (i=0; i<16; i++) { - u32 data; - eeprom_clk_hi(ee); - res <<= 1; - data = readl(ee->addr); -//printk("eeprom_readw: %08x\n", data); - res |= !!(data & ee->eedo) ^ !!(ee->polarity & EEPOL_EEDO); - eeprom_clk_lo(ee); - } - eeprom_update(ee, ee->eesel, 0 ^ !!(ee->polarity & EEPOL_EESEL)); - - return res; -} - - -void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data) -{ -} -- cgit v1.2.3 From dbebb4cbe02dc811e21bd3bc40a252490e46b949 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 10:40:10 +0000 Subject: [ARM SMP] Add missing SMP timer handling for realview Until we have local timer support, we need to broadcast the timer interrupt to the other CPUs. Also, add the missing smp_send_timer() prototype to asm/smp.h Signed-off-by: Russell King --- arch/arm/mach-realview/core.c | 5 +++++ include/asm-arm/smp.h | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'include') diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 482eb512ebe8..4ea60d8b6e36 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -550,6 +550,11 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_reg timer_tick(regs); +#ifdef CONFIG_SMP + smp_send_timer(); + update_process_times(user_mode(regs)); +#endif + write_sequnlock(&xtime_lock); return IRQ_HANDLED; diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 551cd3c3093c..21d1723c03e1 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -46,6 +46,11 @@ extern void smp_store_cpu_info(unsigned int cpuid); */ extern void smp_cross_call(cpumask_t callmap); +/* + * Broadcast a timer interrupt to the other CPUs. + */ +extern void smp_send_timer(void); + /* * Boot a secondary CPU, and assign it the specified idle task. * This also gives us the initial stack to use for this CPU. -- cgit v1.2.3 From 3b6353fae0d7ba772d7eb2651727332c9e9c74ac Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 15:35:23 +0000 Subject: [ARM] Declare asm entry points in asm/smp.h Signed-off-by: Russell King --- include/asm-arm/smp.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include') diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 21d1723c03e1..52e7c8d830b2 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -36,6 +36,11 @@ struct seq_file; */ extern void show_ipi_list(struct seq_file *p); +/* + * Called from assembly code, this handles an IPI. + */ +asmlinkage void do_IPI(struct pt_regs *regs); + /* * Move global data into per-processor storage. */ @@ -57,6 +62,12 @@ extern void smp_send_timer(void); */ extern int boot_secondary(unsigned int cpu, struct task_struct *); +/* + * Called from platform specific assembly code, this is the + * secondary CPU entry point. + */ +asmlinkage void secondary_start_kernel(void); + /* * Perform platform specific initialisation of the specified CPU. */ -- cgit v1.2.3 From 971f359ddcb2e7a0d577479c7561bda407febe1b Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 8 Nov 2005 09:37:56 -0800 Subject: [IPV6]: Put addr_diff() into common header for future use. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/ipv6.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ net/ipv6/ip6_fib.c | 54 ++---------------------------------------------------- 2 files changed, 50 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 65ec86678a08..98661fa4fc78 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -340,6 +340,54 @@ static inline int ipv6_addr_any(const struct in6_addr *a) a->s6_addr32[2] | a->s6_addr32[3] ) == 0); } +/* + * find the first different bit between two addresses + * length of address must be a multiple of 32bits + */ +static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen) +{ + const __u32 *a1 = token1, *a2 = token2; + int i; + + addrlen >>= 2; + + for (i = 0; i < addrlen; i++) { + __u32 xb = a1[i] ^ a2[i]; + if (xb) { + int j = 31; + + xb = ntohl(xb); + while ((xb & (1 << j)) == 0) + j--; + + return (i * 32 + 31 - j); + } + } + + /* + * we should *never* get to this point since that + * would mean the addrs are equal + * + * However, we do get to it 8) And exacly, when + * addresses are equal 8) + * + * ip route add 1111::/128 via ... + * ip route add 1111::/64 via ... + * and we are here. + * + * Ideally, this function should stop comparison + * at prefix length. It does not, but it is still OK, + * if returned value is greater than prefix length. + * --ANK (980803) + */ + return (addrlen << 5); +} + +static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2) +{ + return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); +} + /* * Prototypes exported by ipv6 */ diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 4fcc5a7acf6e..1bf6d9a769e6 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -127,56 +127,6 @@ static __inline__ int addr_bit_set(void *token, int fn_bit) return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; } -/* - * find the first different bit between two addresses - * length of address must be a multiple of 32bits - */ - -static __inline__ int addr_diff(void *token1, void *token2, int addrlen) -{ - __u32 *a1 = token1; - __u32 *a2 = token2; - int i; - - addrlen >>= 2; - - for (i = 0; i < addrlen; i++) { - __u32 xb; - - xb = a1[i] ^ a2[i]; - - if (xb) { - int j = 31; - - xb = ntohl(xb); - - while ((xb & (1 << j)) == 0) - j--; - - return (i * 32 + 31 - j); - } - } - - /* - * we should *never* get to this point since that - * would mean the addrs are equal - * - * However, we do get to it 8) And exacly, when - * addresses are equal 8) - * - * ip route add 1111::/128 via ... - * ip route add 1111::/64 via ... - * and we are here. - * - * Ideally, this function should stop comparison - * at prefix length. It does not, but it is still OK, - * if returned value is greater than prefix length. - * --ANK (980803) - */ - - return addrlen<<5; -} - static __inline__ struct fib6_node * node_alloc(void) { struct fib6_node *fn; @@ -296,11 +246,11 @@ insert_above: /* find 1st bit in difference between the 2 addrs. - See comment in addr_diff: bit may be an invalid value, + See comment in __ipv6_addr_diff: bit may be an invalid value, but if it is >= plen, the value is ignored in any case. */ - bit = addr_diff(addr, &key->addr, addrlen); + bit = __ipv6_addr_diff(addr, &key->addr, addrlen); /* * (intermediate)[in] -- cgit v1.2.3 From b1cacb6820e0afc4aeeea67bcb5296a316862cad Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 8 Nov 2005 09:38:12 -0800 Subject: [IPV6]: Make ipv6_addr_type() more generic so that we can use it for source address selection. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/ipv6.h | 19 +++++++++-- net/ipv6/addrconf.c | 90 +++++++++++++++++++++++++++------------------------- net/ipv6/ipv6_syms.c | 2 +- 3 files changed, 64 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 98661fa4fc78..6addb4d464d6 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -252,12 +252,25 @@ typedef int (*inet_getfrag_t) (const void *data, char *, unsigned int, unsigned int); - -extern int ipv6_addr_type(const struct in6_addr *addr); +extern int __ipv6_addr_type(const struct in6_addr *addr); +static inline int ipv6_addr_type(const struct in6_addr *addr) +{ + return __ipv6_addr_type(addr) & 0xffff; +} static inline int ipv6_addr_scope(const struct in6_addr *addr) { - return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; + return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; +} + +static inline int __ipv6_addr_src_scope(int type) +{ + return (type == IPV6_ADDR_ANY ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16)); +} + +static inline int ipv6_addr_src_scope(const struct in6_addr *addr) +{ + return __ipv6_addr_src_scope(__ipv6_addr_type(addr)); } static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2c5f57299d63..ff895da6395b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -35,6 +35,9 @@ * YOSHIFUJI Hideaki @USAGI : ARCnet support * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to * seq_file. + * YOSHIFUJI Hideaki @USAGI : improved source address + * selection; consider scope, + * status etc. */ #include @@ -193,46 +196,51 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; #endif const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; -int ipv6_addr_type(const struct in6_addr *addr) +#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) + +static inline unsigned ipv6_addr_scope2type(unsigned scope) +{ + switch(scope) { + case IPV6_ADDR_SCOPE_NODELOCAL: + return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | + IPV6_ADDR_LOOPBACK); + case IPV6_ADDR_SCOPE_LINKLOCAL: + return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | + IPV6_ADDR_LINKLOCAL); + case IPV6_ADDR_SCOPE_SITELOCAL: + return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | + IPV6_ADDR_SITELOCAL); + } + return IPV6_ADDR_SCOPE_TYPE(scope); +} + +int __ipv6_addr_type(const struct in6_addr *addr) { - int type; u32 st; st = addr->s6_addr32[0]; - if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { - type = IPV6_ADDR_MULTICAST; - - switch((st & htonl(0x00FF0000))) { - case __constant_htonl(0x00010000): - type |= IPV6_ADDR_LOOPBACK; - break; - - case __constant_htonl(0x00020000): - type |= IPV6_ADDR_LINKLOCAL; - break; - - case __constant_htonl(0x00050000): - type |= IPV6_ADDR_SITELOCAL; - break; - }; - return type; - } - - type = IPV6_ADDR_UNICAST; - /* Consider all addresses with the first three bits different of - 000 and 111 as finished. + 000 and 111 as unicasts. */ if ((st & htonl(0xE0000000)) != htonl(0x00000000) && (st & htonl(0xE0000000)) != htonl(0xE0000000)) - return type; - - if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) - return (IPV6_ADDR_LINKLOCAL | type); + return (IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); + if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { + /* multicast */ + /* addr-select 3.1 */ + return (IPV6_ADDR_MULTICAST | + ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); + } + + if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) + return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) - return (IPV6_ADDR_SITELOCAL | type); + return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { if (addr->s6_addr32[2] == 0) { @@ -240,24 +248,20 @@ int ipv6_addr_type(const struct in6_addr *addr) return IPV6_ADDR_ANY; if (addr->s6_addr32[3] == htonl(0x00000001)) - return (IPV6_ADDR_LOOPBACK | type); + return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ - return (IPV6_ADDR_COMPATv4 | type); + return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ } if (addr->s6_addr32[2] == htonl(0x0000ffff)) - return IPV6_ADDR_MAPPED; - } - - st &= htonl(0xFF000000); - if (st == 0) - return IPV6_ADDR_RESERVED; - st &= htonl(0xFE000000); - if (st == htonl(0x02000000)) - return IPV6_ADDR_RESERVED; /* for NSAP */ - if (st == htonl(0x04000000)) - return IPV6_ADDR_RESERVED; /* for IPX */ - return type; + return (IPV6_ADDR_MAPPED | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ + } + + return (IPV6_ADDR_RESERVED | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ } static void addrconf_del_timer(struct inet6_ifaddr *ifp) diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 37a4a99c9fe9..16482785bdfd 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c @@ -7,7 +7,7 @@ #include #include -EXPORT_SYMBOL(ipv6_addr_type); +EXPORT_SYMBOL(__ipv6_addr_type); EXPORT_SYMBOL(icmpv6_send); EXPORT_SYMBOL(icmpv6_statistics); EXPORT_SYMBOL(icmpv6_err_convert); -- cgit v1.2.3 From 9ee6b535af4c2c97b4e3b88f37f244bf1004ebd4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 09:39:42 -0800 Subject: [NET]: sk_add_backlog convert from macro to inline There is no reason for sk_add_backlog to be a macro. It can just be an inline function and get type checking. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/sock.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/net/sock.h b/include/net/sock.h index e0498bd36004..ff13c4cc287a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -461,16 +461,16 @@ static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb) } /* The per-socket spinlock must be held here. */ -#define sk_add_backlog(__sk, __skb) \ -do { if (!(__sk)->sk_backlog.tail) { \ - (__sk)->sk_backlog.head = \ - (__sk)->sk_backlog.tail = (__skb); \ - } else { \ - ((__sk)->sk_backlog.tail)->next = (__skb); \ - (__sk)->sk_backlog.tail = (__skb); \ - } \ - (__skb)->next = NULL; \ -} while(0) +static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb) +{ + if (!sk->sk_backlog.tail) { + sk->sk_backlog.head = sk->sk_backlog.tail = skb; + } else { + sk->sk_backlog.tail->next = skb; + sk->sk_backlog.tail = skb; + } + skb->next = NULL; +} #define sk_wait_event(__sk, __timeo, __condition) \ ({ int rc; \ -- cgit v1.2.3 From b3f9b92a6ec1a9a5e4b4b36e484f2f62cc73277c Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Tue, 8 Nov 2005 09:40:47 -0800 Subject: [PPP]: add PPP MPPE encryption module From: Matt Domsch The patch below implements the Microsoft Point-to-Point Encryption method as a PPP compressor/decompressor. This is necessary for Linux clients and servers to interoperate with Microsoft Point-to-Point Tunneling Protocol (PPTP) servers (either Microsoft PPTP servers or the poptop project) which use MPPE to encrypt data when creating a VPN. This patch differs from the kernel_ppp_mppe DKMS pacakge at pptpclient.sourceforge.net by utilizing the kernel crypto routines rather than providing its own SHA1 and arcfour implementations. Minor changes to ppp_generic.c try to prevent a link from disabling compression (in our case, the encryption) after it has started using compression (encryption). Feedback to please. Signed-off-by: Matt Domsch Cc: James Cameron Cc: "David S. Miller" Signed-off-by: Brice Goglin Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/Kconfig | 13 + drivers/net/Makefile | 1 + drivers/net/ppp_generic.c | 88 ++++-- drivers/net/ppp_mppe.c | 724 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ppp_mppe.h | 86 ++++++ include/linux/if_ppp.h | 7 +- include/linux/ppp-comp.h | 9 + 7 files changed, 902 insertions(+), 26 deletions(-) create mode 100644 drivers/net/ppp_mppe.c create mode 100644 drivers/net/ppp_mppe.h (limited to 'include') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1958d9e16a3a..24f1691b84f9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2523,6 +2523,19 @@ config PPP_BSDCOMP module; it is called bsd_comp and will show up in the directory modules once you have said "make modules". If unsure, say N. +config PPP_MPPE + tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)" + depends on PPP && EXPERIMENTAL + select CRYPTO + select CRYPTO_SHA1 + select CRYPTO_ARC4 + ---help--- + Support for the MPPE Encryption protocol, as employed by the + Microsoft Point-to-Point Tunneling Protocol. + + See http://pptpclient.sourceforge.net/ for information on + configuring PPTP clients and servers to utilize this method. + config PPPOE tristate "PPP over Ethernet (EXPERIMENTAL)" depends on EXPERIMENTAL && PPP diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 7c313cb341b8..4cffd34442aa 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -112,6 +112,7 @@ obj-$(CONFIG_PPP_ASYNC) += ppp_async.o obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o +obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index d3c9958b00d0..50430f79f8cf 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -137,13 +137,14 @@ struct ppp { /* * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC, - * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP. + * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP, + * SC_MUST_COMP * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. * Bits in xstate: SC_COMP_RUN */ #define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \ |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \ - |SC_COMP_TCP|SC_REJ_COMP_TCP) + |SC_COMP_TCP|SC_REJ_COMP_TCP|SC_MUST_COMP) /* * Private data structure for each channel. @@ -1027,6 +1028,56 @@ ppp_xmit_process(struct ppp *ppp) ppp_xmit_unlock(ppp); } +static inline struct sk_buff * +pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int len; + int new_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) + printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + return NULL; + } + if (ppp->dev->hard_header_len > PPP_HDRLEN) + skb_reserve(new_skb, + ppp->dev->hard_header_len - PPP_HDRLEN); + + /* compressor still expects A/C bytes in hdr */ + len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, + new_skb->data, skb->len + 2, + compressor_skb_size); + if (len > 0 && (ppp->flags & SC_CCP_UP)) { + kfree_skb(skb); + skb = new_skb; + skb_put(skb, len); + skb_pull(skb, 2); /* pull off A/C bytes */ + } else if (len == 0) { + /* didn't compress, or CCP not up yet */ + kfree_skb(new_skb); + new_skb = skb; + } else { + /* + * (len < 0) + * MPPE requires that we do not send unencrypted + * frames. The compressor will return -1 if we + * should drop the frame. We cannot simply test + * the compress_proto because MPPE and MPPC share + * the same number. + */ + if (net_ratelimit()) + printk(KERN_ERR "ppp: compressor dropped pkt\n"); + kfree_skb(skb); + kfree_skb(new_skb); + new_skb = NULL; + } + return new_skb; +} + /* * Compress and send a frame. * The caller should have locked the xmit path, @@ -1113,29 +1164,14 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) /* try to do packet compression */ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 && proto != PPP_LCP && proto != PPP_CCP) { - new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len, - GFP_ATOMIC); - if (new_skb == 0) { - printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) { + if (net_ratelimit()) + printk(KERN_ERR "ppp: compression required but down - pkt dropped.\n"); goto drop; } - if (ppp->dev->hard_header_len > PPP_HDRLEN) - skb_reserve(new_skb, - ppp->dev->hard_header_len - PPP_HDRLEN); - - /* compressor still expects A/C bytes in hdr */ - len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, - new_skb->data, skb->len + 2, - ppp->dev->mtu + PPP_HDRLEN); - if (len > 0 && (ppp->flags & SC_CCP_UP)) { - kfree_skb(skb); - skb = new_skb; - skb_put(skb, len); - skb_pull(skb, 2); /* pull off A/C bytes */ - } else { - /* didn't compress, or CCP not up yet */ - kfree_skb(new_skb); - } + skb = pad_compress_skb(ppp, skb); + if (!skb) + goto drop; } /* @@ -1155,7 +1191,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) return; drop: - kfree_skb(skb); + if (skb) + kfree_skb(skb); ++ppp->stats.tx_errors; } @@ -1552,6 +1589,9 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) skb = ppp_decompress_frame(ppp, skb); + if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR) + goto err; + proto = PPP_PROTO(skb); switch (proto) { case PPP_VJC_COMP: diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c new file mode 100644 index 000000000000..1985d1b57c45 --- /dev/null +++ b/drivers/net/ppp_mppe.c @@ -0,0 +1,724 @@ +/* + * ppp_mppe.c - interface MPPE to the PPP code. + * This version is for use with Linux kernel 2.6.14+ + * + * By Frank Cusack . + * Copyright (c) 2002,2003,2004 Google, Inc. + * All rights reserved. + * + * License: + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Changelog: + * 08/12/05 - Matt Domsch + * Only need extra skb padding on transmit, not receive. + * 06/18/04 - Matt Domsch , Oleg Makarenko + * Use Linux kernel 2.6 arc4 and sha1 routines rather than + * providing our own. + * 2/15/04 - TS: added #include and testing for Kernel + * version before using + * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are + * deprecated in 2.6 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ppp_mppe.h" + +MODULE_AUTHOR("Frank Cusack "); +MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); +MODULE_VERSION("1.0.2"); + +static void +setup_sg(struct scatterlist *sg, const void *address, unsigned int length) +{ + sg[0].page = virt_to_page(address); + sg[0].offset = offset_in_page(address); + sg[0].length = length; +} + +#define SHA1_PAD_SIZE 40 + +/* + * kernel crypto API needs its arguments to be in kmalloc'd memory, not in the module + * static data area. That means sha_pad needs to be kmalloc'd. + */ + +struct sha_pad { + unsigned char sha_pad1[SHA1_PAD_SIZE]; + unsigned char sha_pad2[SHA1_PAD_SIZE]; +}; +static struct sha_pad *sha_pad; + +static inline void sha_pad_init(struct sha_pad *shapad) +{ + memset(shapad->sha_pad1, 0x00, sizeof(shapad->sha_pad1)); + memset(shapad->sha_pad2, 0xF2, sizeof(shapad->sha_pad2)); +} + +/* + * State for an MPPE (de)compressor. + */ +struct ppp_mppe_state { + struct crypto_tfm *arc4; + struct crypto_tfm *sha1; + unsigned char *sha1_digest; + unsigned char master_key[MPPE_MAX_KEY_LEN]; + unsigned char session_key[MPPE_MAX_KEY_LEN]; + unsigned keylen; /* key length in bytes */ + /* NB: 128-bit == 16, 40-bit == 8! */ + /* If we want to support 56-bit, */ + /* the unit has to change to bits */ + unsigned char bits; /* MPPE control bits */ + unsigned ccount; /* 12-bit coherency count (seqno) */ + unsigned stateful; /* stateful mode flag */ + int discard; /* stateful mode packet loss flag */ + int sanity_errors; /* take down LCP if too many */ + int unit; + int debug; + struct compstat stats; +}; + +/* struct ppp_mppe_state.bits definitions */ +#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ +#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ +#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ +#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ + +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D + +#define MPPE_BITS(p) ((p)[4] & 0xf0) +#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5]) +#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ + +#define MPPE_OVHD 2 /* MPPE overhead/packet */ +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ + +/* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ +static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey) +{ + struct scatterlist sg[4]; + + setup_sg(&sg[0], state->master_key, state->keylen); + setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1)); + setup_sg(&sg[2], state->session_key, state->keylen); + setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); + + crypto_digest_digest (state->sha1, sg, 4, state->sha1_digest); + + memcpy(InterimKey, state->sha1_digest, state->keylen); +} + +/* + * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. + * Well, not what's written there, but rather what they meant. + */ +static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) +{ + unsigned char InterimKey[MPPE_MAX_KEY_LEN]; + struct scatterlist sg_in[1], sg_out[1]; + + get_new_key_from_sha(state, InterimKey); + if (!initial_key) { + crypto_cipher_setkey(state->arc4, InterimKey, state->keylen); + setup_sg(sg_in, InterimKey, state->keylen); + setup_sg(sg_out, state->session_key, state->keylen); + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, + state->keylen) != 0) { + printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); + } + } else { + memcpy(state->session_key, InterimKey, state->keylen); + } + if (state->keylen == 8) { + /* See RFC 3078 */ + state->session_key[0] = 0xd1; + state->session_key[1] = 0x26; + state->session_key[2] = 0x9e; + } + crypto_cipher_setkey(state->arc4, state->session_key, state->keylen); +} + +/* + * Allocate space for a (de)compressor. + */ +static void *mppe_alloc(unsigned char *options, int optlen) +{ + struct ppp_mppe_state *state; + unsigned int digestsize; + + if (optlen != CILEN_MPPE + sizeof(state->master_key) + || options[0] != CI_MPPE || options[1] != CILEN_MPPE) + goto out; + + state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) + goto out; + + memset(state, 0, sizeof(*state)); + + state->arc4 = crypto_alloc_tfm("arc4", 0); + if (!state->arc4) + goto out_free; + + state->sha1 = crypto_alloc_tfm("sha1", 0); + if (!state->sha1) + goto out_free; + + digestsize = crypto_tfm_alg_digestsize(state->sha1); + if (digestsize < MPPE_MAX_KEY_LEN) + goto out_free; + + state->sha1_digest = kmalloc(digestsize, GFP_KERNEL); + if (!state->sha1_digest) + goto out_free; + + /* Save keys. */ + memcpy(state->master_key, &options[CILEN_MPPE], + sizeof(state->master_key)); + memcpy(state->session_key, state->master_key, + sizeof(state->master_key)); + + /* + * We defer initial key generation until mppe_init(), as mppe_alloc() + * is called frequently during negotiation. + */ + + return (void *)state; + + out_free: + if (state->sha1_digest) + kfree(state->sha1_digest); + if (state->sha1) + crypto_free_tfm(state->sha1); + if (state->arc4) + crypto_free_tfm(state->arc4); + kfree(state); + out: + return NULL; +} + +/* + * Deallocate space for a (de)compressor. + */ +static void mppe_free(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + if (state) { + if (state->sha1_digest) + kfree(state->sha1_digest); + if (state->sha1) + crypto_free_tfm(state->sha1); + if (state->arc4) + crypto_free_tfm(state->arc4); + kfree(state); + } +} + +/* + * Initialize (de)compressor state. + */ +static int +mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug, + const char *debugstr) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + unsigned char mppe_opts; + + if (optlen != CILEN_MPPE + || options[0] != CI_MPPE || options[1] != CILEN_MPPE) + return 0; + + MPPE_CI_TO_OPTS(&options[2], mppe_opts); + if (mppe_opts & MPPE_OPT_128) + state->keylen = 16; + else if (mppe_opts & MPPE_OPT_40) + state->keylen = 8; + else { + printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, + unit); + return 0; + } + if (mppe_opts & MPPE_OPT_STATEFUL) + state->stateful = 1; + + /* Generate the initial session key. */ + mppe_rekey(state, 1); + + if (debug) { + int i; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; + + printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", + debugstr, unit, (state->keylen == 16) ? 128 : 40, + (state->stateful) ? "stateful" : "stateless"); + + for (i = 0; i < sizeof(state->master_key); i++) + sprintf(mkey + i * 2, "%02x", state->master_key[i]); + for (i = 0; i < sizeof(state->session_key); i++) + sprintf(skey + i * 2, "%02x", state->session_key[i]); + printk(KERN_DEBUG + "%s[%d]: keys: master: %s initial session: %s\n", + debugstr, unit, mkey, skey); + } + + /* + * Initialize the coherency count. The initial value is not specified + * in RFC 3078, but we can make a reasonable assumption that it will + * start at 0. Setting it to the max here makes the comp/decomp code + * do the right thing (determined through experiment). + */ + state->ccount = MPPE_CCOUNT_SPACE - 1; + + /* + * Note that even though we have initialized the key table, we don't + * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. + */ + state->bits = MPPE_BIT_ENCRYPTED; + + state->unit = unit; + state->debug = debug; + + return 1; +} + +static int +mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit, + int hdrlen, int debug) +{ + /* ARGSUSED */ + return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init"); +} + +/* + * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), + * tell the compressor to rekey. Note that we MUST NOT rekey for + * every CCP Reset-Request; we only rekey on the next xmit packet. + * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. + * So, rekeying for every CCP Reset-Request is broken as the peer will not + * know how many times we've rekeyed. (If we rekey and THEN get another + * CCP Reset-Request, we must rekey again.) + */ +static void mppe_comp_reset(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + state->bits |= MPPE_BIT_FLUSHED; +} + +/* + * Compress (encrypt) a packet. + * It's strange to call this a compressor, since the output is always + * MPPE_OVHD + 2 bytes larger than the input. + */ +static int +mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, + int isize, int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + int proto; + struct scatterlist sg_in[1], sg_out[1]; + + /* + * Check that the protocol is in the range we handle. + */ + proto = PPP_PROTOCOL(ibuf); + if (proto < 0x0021 || proto > 0x00fa) + return 0; + + /* Make sure we have enough room to generate an encrypted packet. */ + if (osize < isize + MPPE_OVHD + 2) { + /* Drop the packet if we should encrypt it, but can't. */ + printk(KERN_DEBUG "mppe_compress[%d]: osize too small! " + "(have: %d need: %d)\n", state->unit, + osize, osize + MPPE_OVHD + 2); + return -1; + } + + osize = isize + MPPE_OVHD + 2; + + /* + * Copy over the PPP header and set control bits. + */ + obuf[0] = PPP_ADDRESS(ibuf); + obuf[1] = PPP_CONTROL(ibuf); + obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */ + obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */ + obuf += PPP_HDRLEN; + + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (state->debug >= 7) + printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit, + state->ccount); + obuf[0] = state->ccount >> 8; + obuf[1] = state->ccount & 0xff; + + if (!state->stateful || /* stateless mode */ + ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ + (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ + /* We must rekey */ + if (state->debug && state->stateful) + printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", + state->unit); + mppe_rekey(state, 0); + state->bits |= MPPE_BIT_FLUSHED; + } + obuf[0] |= state->bits; + state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ + + obuf += MPPE_OVHD; + ibuf += 2; /* skip to proto field */ + isize -= 2; + + /* Encrypt packet */ + setup_sg(sg_in, ibuf, isize); + setup_sg(sg_out, obuf, osize); + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, isize) != 0) { + printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); + return -1; + } + + state->stats.unc_bytes += isize; + state->stats.unc_packets++; + state->stats.comp_bytes += osize; + state->stats.comp_packets++; + + return osize; +} + +/* + * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going + * to look bad ... and the longer the link is up the worse it will get. + */ +static void mppe_comp_stats(void *arg, struct compstat *stats) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + *stats = state->stats; +} + +static int +mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit, + int hdrlen, int mru, int debug) +{ + /* ARGSUSED */ + return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init"); +} + +/* + * We received a CCP Reset-Ack. Just ignore it. + */ +static void mppe_decomp_reset(void *arg) +{ + /* ARGSUSED */ + return; +} + +/* + * Decompress (decrypt) an MPPE packet. + */ +static int +mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, + int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + unsigned ccount; + int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; + int sanity = 0; + struct scatterlist sg_in[1], sg_out[1]; + + if (isize <= PPP_HDRLEN + MPPE_OVHD) { + if (state->debug) + printk(KERN_DEBUG + "mppe_decompress[%d]: short pkt (%d)\n", + state->unit, isize); + return DECOMP_ERROR; + } + + /* + * Make sure we have enough room to decrypt the packet. + * Note that for our test we only subtract 1 byte whereas in + * mppe_compress() we added 2 bytes (+MPPE_OVHD); + * this is to account for possible PFC. + */ + if (osize < isize - MPPE_OVHD - 1) { + printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! " + "(have: %d need: %d)\n", state->unit, + osize, isize - MPPE_OVHD - 1); + return DECOMP_ERROR; + } + osize = isize - MPPE_OVHD - 2; /* assume no PFC */ + + ccount = MPPE_CCOUNT(ibuf); + if (state->debug >= 7) + printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", + state->unit, ccount); + + /* sanity checks -- terminate with extreme prejudice */ + if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) { + printk(KERN_DEBUG + "mppe_decompress[%d]: ENCRYPTED bit not set!\n", + state->unit); + state->sanity_errors += 100; + sanity = 1; + } + if (!state->stateful && !flushed) { + printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in " + "stateless mode!\n", state->unit); + state->sanity_errors += 100; + sanity = 1; + } + if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { + printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on " + "flag packet!\n", state->unit); + state->sanity_errors += 100; + sanity = 1; + } + + if (sanity) { + if (state->sanity_errors < SANITY_MAX) + return DECOMP_ERROR; + else + /* + * Take LCP down if the peer is sending too many bogons. + * We don't want to do this for a single or just a few + * instances since it could just be due to packet corruption. + */ + return DECOMP_FATALERROR; + } + + /* + * Check the coherency count. + */ + + if (!state->stateful) { + /* RFC 3078, sec 8.1. Rekey for every packet. */ + while (state->ccount != ccount) { + mppe_rekey(state, 0); + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + } + } else { + /* RFC 3078, sec 8.2. */ + if (!state->discard) { + /* normal state */ + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (ccount != state->ccount) { + /* + * (ccount > state->ccount) + * Packet loss detected, enter the discard state. + * Signal the peer to rekey (by sending a CCP Reset-Request). + */ + state->discard = 1; + return DECOMP_ERROR; + } + } else { + /* discard state */ + if (!flushed) { + /* ccp.c will be silent (no additional CCP Reset-Requests). */ + return DECOMP_ERROR; + } else { + /* Rekey for every missed "flag" packet. */ + while ((ccount & ~0xff) != + (state->ccount & ~0xff)) { + mppe_rekey(state, 0); + state->ccount = + (state->ccount + + 256) % MPPE_CCOUNT_SPACE; + } + + /* reset */ + state->discard = 0; + state->ccount = ccount; + /* + * Another problem with RFC 3078 here. It implies that the + * peer need not send a Reset-Ack packet. But RFC 1962 + * requires it. Hopefully, M$ does send a Reset-Ack; even + * though it isn't required for MPPE synchronization, it is + * required to reset CCP state. + */ + } + } + if (flushed) + mppe_rekey(state, 0); + } + + /* + * Fill in the first part of the PPP header. The protocol field + * comes from the decrypted data. + */ + obuf[0] = PPP_ADDRESS(ibuf); /* +1 */ + obuf[1] = PPP_CONTROL(ibuf); /* +1 */ + obuf += 2; + ibuf += PPP_HDRLEN + MPPE_OVHD; + isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */ + /* net osize: isize-4 */ + + /* + * Decrypt the first byte in order to check if it is + * a compressed or uncompressed protocol field. + */ + setup_sg(sg_in, ibuf, 1); + setup_sg(sg_out, obuf, 1); + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, 1) != 0) { + printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); + return DECOMP_ERROR; + } + + /* + * Do PFC decompression. + * This would be nicer if we were given the actual sk_buff + * instead of a char *. + */ + if ((obuf[0] & 0x01) != 0) { + obuf[1] = obuf[0]; + obuf[0] = 0; + obuf++; + osize++; + } + + /* And finally, decrypt the rest of the packet. */ + setup_sg(sg_in, ibuf + 1, isize - 1); + setup_sg(sg_out, obuf + 1, osize - 1); + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, isize - 1) != 0) { + printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); + return DECOMP_ERROR; + } + + state->stats.unc_bytes += osize; + state->stats.unc_packets++; + state->stats.comp_bytes += isize; + state->stats.comp_packets++; + + /* good packet credit */ + state->sanity_errors >>= 1; + + return osize; +} + +/* + * Incompressible data has arrived (this should never happen!). + * We should probably drop the link if the protocol is in the range + * of what should be encrypted. At the least, we should drop this + * packet. (How to do this?) + */ +static void mppe_incomp(void *arg, unsigned char *ibuf, int icnt) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + if (state->debug && + (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa)) + printk(KERN_DEBUG + "mppe_incomp[%d]: incompressible (unencrypted) data! " + "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf)); + + state->stats.inc_bytes += icnt; + state->stats.inc_packets++; + state->stats.unc_bytes += icnt; + state->stats.unc_packets++; +} + +/************************************************************* + * Module interface table + *************************************************************/ + +/* + * Procedures exported to if_ppp.c. + */ +static struct compressor ppp_mppe = { + .compress_proto = CI_MPPE, + .comp_alloc = mppe_alloc, + .comp_free = mppe_free, + .comp_init = mppe_comp_init, + .comp_reset = mppe_comp_reset, + .compress = mppe_compress, + .comp_stat = mppe_comp_stats, + .decomp_alloc = mppe_alloc, + .decomp_free = mppe_free, + .decomp_init = mppe_decomp_init, + .decomp_reset = mppe_decomp_reset, + .decompress = mppe_decompress, + .incomp = mppe_incomp, + .decomp_stat = mppe_comp_stats, + .owner = THIS_MODULE, + .comp_extra = MPPE_PAD, +}; + +/* + * ppp_mppe_init() + * + * Prior to allowing load, try to load the arc4 and sha1 crypto + * libraries. The actual use will be allocated later, but + * this way the module will fail to insmod if they aren't available. + */ + +static int __init ppp_mppe_init(void) +{ + int answer; + if (!(crypto_alg_available("arc4", 0) && + crypto_alg_available("sha1", 0))) + return -ENODEV; + + sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); + if (!sha_pad) + return -ENOMEM; + sha_pad_init(sha_pad); + + answer = ppp_register_compressor(&ppp_mppe); + + if (answer == 0) + printk(KERN_INFO "PPP MPPE Compression module registered\n"); + else + kfree(sha_pad); + + return answer; +} + +static void __exit ppp_mppe_cleanup(void) +{ + ppp_unregister_compressor(&ppp_mppe); + kfree(sha_pad); +} + +module_init(ppp_mppe_init); +module_exit(ppp_mppe_cleanup); diff --git a/drivers/net/ppp_mppe.h b/drivers/net/ppp_mppe.h new file mode 100644 index 000000000000..7a14e058c668 --- /dev/null +++ b/drivers/net/ppp_mppe.h @@ -0,0 +1,86 @@ +#define MPPE_PAD 4 /* MPPE growth per frame */ +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ + +/* option bits for ccp_options.mppe */ +#define MPPE_OPT_40 0x01 /* 40 bit */ +#define MPPE_OPT_128 0x02 /* 128 bit */ +#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ +/* unsupported opts */ +#define MPPE_OPT_56 0x08 /* 56 bit */ +#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ +#define MPPE_OPT_D 0x20 /* Unknown */ +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) +#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ + +/* + * This is not nice ... the alternative is a bitfield struct though. + * And unfortunately, we cannot share the same bits for the option + * names above since C and H are the same bit. We could do a u_int32 + * but then we have to do a htonl() all the time and/or we still need + * to know which octet is which. + */ +#define MPPE_C_BIT 0x01 /* MPPC */ +#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ +#define MPPE_L_BIT 0x20 /* 40-bit */ +#define MPPE_S_BIT 0x40 /* 128-bit */ +#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ +#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ + +/* Does not include H bit; used for least significant octet only. */ +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) + +/* Build a CI from mppe opts (see RFC 3078) */ +#define MPPE_OPTS_TO_CI(opts, ci) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + /* H bit */ \ + if (opts & MPPE_OPT_STATEFUL) \ + *ptr++ = 0x0; \ + else \ + *ptr++ = MPPE_H_BIT; \ + *ptr++ = 0; \ + *ptr++ = 0; \ + \ + /* S,L bits */ \ + *ptr = 0; \ + if (opts & MPPE_OPT_128) \ + *ptr |= MPPE_S_BIT; \ + if (opts & MPPE_OPT_40) \ + *ptr |= MPPE_L_BIT; \ + /* M,D,C bits not supported */ \ + } while (/* CONSTCOND */ 0) + +/* The reverse of the above */ +#define MPPE_CI_TO_OPTS(ci, opts) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + opts = 0; \ + \ + /* H bit */ \ + if (!(ptr[0] & MPPE_H_BIT)) \ + opts |= MPPE_OPT_STATEFUL; \ + \ + /* S,L bits */ \ + if (ptr[3] & MPPE_S_BIT) \ + opts |= MPPE_OPT_128; \ + if (ptr[3] & MPPE_L_BIT) \ + opts |= MPPE_OPT_40; \ + \ + /* M,D,C bits */ \ + if (ptr[3] & MPPE_M_BIT) \ + opts |= MPPE_OPT_56; \ + if (ptr[3] & MPPE_D_BIT) \ + opts |= MPPE_OPT_D; \ + if (ptr[3] & MPPE_C_BIT) \ + opts |= MPPE_OPT_MPPC; \ + \ + /* Other bits */ \ + if (ptr[0] & ~MPPE_H_BIT) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[1] || ptr[2]) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[3] & ~MPPE_ALL_BITS) \ + opts |= MPPE_OPT_UNKNOWN; \ + } while (/* CONSTCOND */ 0) diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index 572aff7daa21..768372f07caa 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h @@ -21,7 +21,7 @@ */ /* - * ==FILEVERSION 20000724== + * ==FILEVERSION 20050812== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -35,6 +35,8 @@ #ifndef _IF_PPP_H_ #define _IF_PPP_H_ +#include + /* * Packet sizes */ @@ -70,7 +72,8 @@ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ #define SC_SYNC 0x00200000 /* synchronous serial mode */ -#define SC_MASK 0x0f200fff /* bits that user can change */ +#define SC_MUST_COMP 0x00400000 /* no uncompressed packets may be sent or received */ +#define SC_MASK 0x0f600fff /* bits that user can change */ /* state bits */ #define SC_XMIT_BUSY 0x10000000 /* (used by isdn_ppp?) */ diff --git a/include/linux/ppp-comp.h b/include/linux/ppp-comp.h index 7227e653b3be..e86a7a5cf355 100644 --- a/include/linux/ppp-comp.h +++ b/include/linux/ppp-comp.h @@ -111,6 +111,8 @@ struct compressor { /* Used in locking compressor modules */ struct module *owner; + /* Extra skb space needed by the compressor algorithm */ + unsigned int comp_extra; }; /* @@ -190,6 +192,13 @@ struct compressor { #define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) #define DEFLATE_CHK_SEQUENCE 0 +/* + * Definitions for MPPE. + */ + +#define CI_MPPE 18 /* config option for MPPE */ +#define CILEN_MPPE 6 /* length of config option */ + /* * Definitions for other, as yet unsupported, compression methods. */ -- cgit v1.2.3 From 1ebb92521d0bc2d4ef772730d29333c06b807191 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 Nov 2005 09:57:21 -0800 Subject: [Bluetooth]: Add endian annotations to the core This patch adds the endian annotations to the Bluetooth core. Signed-off-by: Marcel Holtmann Signed-off-by: David S. Miller --- drivers/bluetooth/bpa10x.c | 4 +- include/net/bluetooth/hci.h | 116 +++++++++++++++++++-------------------- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_event.c | 6 +- net/bluetooth/hci_sock.c | 2 +- 6 files changed, 66 insertions(+), 66 deletions(-) (limited to 'include') diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index ecbeb7eaba8e..394796315adc 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -84,8 +84,8 @@ struct bpa10x_data { struct hci_vendor_hdr { __u8 type; - __u16 snum; - __u16 dlen; + __le16 snum; + __le16 dlen; } __attribute__ ((packed)); static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int count) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index fa2d12b0579b..b06a2d2f63d2 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -184,10 +184,10 @@ enum { struct hci_rp_read_loc_version { __u8 status; __u8 hci_ver; - __u16 hci_rev; + __le16 hci_rev; __u8 lmp_ver; - __u16 manufacturer; - __u16 lmp_subver; + __le16 manufacturer; + __le16 lmp_subver; } __attribute__ ((packed)); #define OCF_READ_LOCAL_FEATURES 0x0003 @@ -199,10 +199,10 @@ struct hci_rp_read_loc_features { #define OCF_READ_BUFFER_SIZE 0x0005 struct hci_rp_read_buffer_size { __u8 status; - __u16 acl_mtu; + __le16 acl_mtu; __u8 sco_mtu; - __u16 acl_max_pkt; - __u16 sco_max_pkt; + __le16 acl_max_pkt; + __le16 sco_max_pkt; } __attribute__ ((packed)); #define OCF_READ_BD_ADDR 0x0009 @@ -267,21 +267,21 @@ struct hci_cp_write_dev_class { #define OCF_READ_VOICE_SETTING 0x0025 struct hci_rp_read_voice_setting { - __u8 status; - __u16 voice_setting; + __u8 status; + __le16 voice_setting; } __attribute__ ((packed)); #define OCF_WRITE_VOICE_SETTING 0x0026 struct hci_cp_write_voice_setting { - __u16 voice_setting; + __le16 voice_setting; } __attribute__ ((packed)); #define OCF_HOST_BUFFER_SIZE 0x0033 struct hci_cp_host_buffer_size { - __u16 acl_mtu; + __le16 acl_mtu; __u8 sco_mtu; - __u16 acl_max_pkt; - __u16 sco_max_pkt; + __le16 acl_max_pkt; + __le16 sco_max_pkt; } __attribute__ ((packed)); /* Link Control */ @@ -289,10 +289,10 @@ struct hci_cp_host_buffer_size { #define OCF_CREATE_CONN 0x0005 struct hci_cp_create_conn { bdaddr_t bdaddr; - __u16 pkt_type; + __le16 pkt_type; __u8 pscan_rep_mode; __u8 pscan_mode; - __u16 clock_offset; + __le16 clock_offset; __u8 role_switch; } __attribute__ ((packed)); @@ -310,14 +310,14 @@ struct hci_cp_reject_conn_req { #define OCF_DISCONNECT 0x0006 struct hci_cp_disconnect { - __u16 handle; + __le16 handle; __u8 reason; } __attribute__ ((packed)); #define OCF_ADD_SCO 0x0007 struct hci_cp_add_sco { - __u16 handle; - __u16 pkt_type; + __le16 handle; + __le16 pkt_type; } __attribute__ ((packed)); #define OCF_INQUIRY 0x0001 @@ -354,56 +354,56 @@ struct hci_cp_pin_code_neg_reply { #define OCF_CHANGE_CONN_PTYPE 0x000F struct hci_cp_change_conn_ptype { - __u16 handle; - __u16 pkt_type; + __le16 handle; + __le16 pkt_type; } __attribute__ ((packed)); #define OCF_AUTH_REQUESTED 0x0011 struct hci_cp_auth_requested { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define OCF_SET_CONN_ENCRYPT 0x0013 struct hci_cp_set_conn_encrypt { - __u16 handle; + __le16 handle; __u8 encrypt; } __attribute__ ((packed)); #define OCF_CHANGE_CONN_LINK_KEY 0x0015 struct hci_cp_change_conn_link_key { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define OCF_READ_REMOTE_FEATURES 0x001B struct hci_cp_read_rmt_features { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define OCF_READ_REMOTE_VERSION 0x001D struct hci_cp_read_rmt_version { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); /* Link Policy */ #define OGF_LINK_POLICY 0x02 #define OCF_ROLE_DISCOVERY 0x0009 struct hci_cp_role_discovery { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); struct hci_rp_role_discovery { __u8 status; - __u16 handle; + __le16 handle; __u8 role; } __attribute__ ((packed)); #define OCF_READ_LINK_POLICY 0x000C struct hci_cp_read_link_policy { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); struct hci_rp_read_link_policy { __u8 status; - __u16 handle; - __u16 policy; + __le16 handle; + __le16 policy; } __attribute__ ((packed)); #define OCF_SWITCH_ROLE 0x000B @@ -414,12 +414,12 @@ struct hci_cp_switch_role { #define OCF_WRITE_LINK_POLICY 0x000D struct hci_cp_write_link_policy { - __u16 handle; - __u16 policy; + __le16 handle; + __le16 policy; } __attribute__ ((packed)); struct hci_rp_write_link_policy { __u8 status; - __u16 handle; + __le16 handle; } __attribute__ ((packed)); /* Status params */ @@ -441,7 +441,7 @@ struct inquiry_info { __u8 pscan_period_mode; __u8 pscan_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; } __attribute__ ((packed)); #define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 @@ -450,7 +450,7 @@ struct inquiry_info_with_rssi { __u8 pscan_rep_mode; __u8 pscan_period_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; } __attribute__ ((packed)); struct inquiry_info_with_rssi_and_pscan_mode { @@ -459,7 +459,7 @@ struct inquiry_info_with_rssi_and_pscan_mode { __u8 pscan_period_mode; __u8 pscan_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; } __attribute__ ((packed)); @@ -469,7 +469,7 @@ struct extended_inquiry_info { __u8 pscan_rep_mode; __u8 pscan_period_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; __u8 data[240]; } __attribute__ ((packed)); @@ -477,7 +477,7 @@ struct extended_inquiry_info { #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { __u8 status; - __u16 handle; + __le16 handle; bdaddr_t bdaddr; __u8 link_type; __u8 encr_mode; @@ -493,27 +493,27 @@ struct hci_ev_conn_request { #define HCI_EV_DISCONN_COMPLETE 0x05 struct hci_ev_disconn_complete { __u8 status; - __u16 handle; + __le16 handle; __u8 reason; } __attribute__ ((packed)); #define HCI_EV_AUTH_COMPLETE 0x06 struct hci_ev_auth_complete { __u8 status; - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define HCI_EV_ENCRYPT_CHANGE 0x08 struct hci_ev_encrypt_change { __u8 status; - __u16 handle; + __le16 handle; __u8 encrypt; } __attribute__ ((packed)); #define HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE 0x09 struct hci_ev_change_conn_link_key_complete { __u8 status; - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define HCI_EV_QOS_SETUP_COMPLETE 0x0D @@ -526,21 +526,21 @@ struct hci_qos { } __attribute__ ((packed)); struct hci_ev_qos_setup_complete { __u8 status; - __u16 handle; + __le16 handle; struct hci_qos qos; } __attribute__ ((packed)); #define HCI_EV_CMD_COMPLETE 0x0E struct hci_ev_cmd_complete { __u8 ncmd; - __u16 opcode; + __le16 opcode; } __attribute__ ((packed)); #define HCI_EV_CMD_STATUS 0x0F struct hci_ev_cmd_status { __u8 status; __u8 ncmd; - __u16 opcode; + __le16 opcode; } __attribute__ ((packed)); #define HCI_EV_NUM_COMP_PKTS 0x13 @@ -559,9 +559,9 @@ struct hci_ev_role_change { #define HCI_EV_MODE_CHANGE 0x14 struct hci_ev_mode_change { __u8 status; - __u16 handle; + __le16 handle; __u8 mode; - __u16 interval; + __le16 interval; } __attribute__ ((packed)); #define HCI_EV_PIN_CODE_REQ 0x16 @@ -584,24 +584,24 @@ struct hci_ev_link_key_notify { #define HCI_EV_RMT_FEATURES 0x0B struct hci_ev_rmt_features { __u8 status; - __u16 handle; + __le16 handle; __u8 features[8]; } __attribute__ ((packed)); #define HCI_EV_RMT_VERSION 0x0C struct hci_ev_rmt_version { __u8 status; - __u16 handle; + __le16 handle; __u8 lmp_ver; - __u16 manufacturer; - __u16 lmp_subver; + __le16 manufacturer; + __le16 lmp_subver; } __attribute__ ((packed)); #define HCI_EV_CLOCK_OFFSET 0x01C struct hci_ev_clock_offset { __u8 status; - __u16 handle; - __u16 clock_offset; + __le16 handle; + __le16 clock_offset; } __attribute__ ((packed)); #define HCI_EV_PSCAN_REP_MODE 0x20 @@ -638,7 +638,7 @@ struct hci_ev_si_security { #define HCI_SCO_HDR_SIZE 3 struct hci_command_hdr { - __u16 opcode; /* OCF & OGF */ + __le16 opcode; /* OCF & OGF */ __u8 plen; } __attribute__ ((packed)); @@ -648,22 +648,22 @@ struct hci_event_hdr { } __attribute__ ((packed)); struct hci_acl_hdr { - __u16 handle; /* Handle & Flags(PB, BC) */ - __u16 dlen; + __le16 handle; /* Handle & Flags(PB, BC) */ + __le16 dlen; } __attribute__ ((packed)); struct hci_sco_hdr { - __u16 handle; + __le16 handle; __u8 dlen; } __attribute__ ((packed)); /* Command opcode pack/unpack */ -#define hci_opcode_pack(ogf, ocf) (__u16)((ocf & 0x03ff)|(ogf << 10)) +#define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10)) #define hci_opcode_ogf(op) (op >> 10) #define hci_opcode_ocf(op) (op & 0x03ff) /* ACL handle and flags pack/unpack */ -#define hci_handle_pack(h, f) (__u16)((h & 0x0fff)|(f << 12)) +#define hci_handle_pack(h, f) (__u16) ((h & 0x0fff)|(f << 12)) #define hci_handle(h) (h & 0x0fff) #define hci_flags(h) (h >> 12) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7f933f302078..adb94508259b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -44,7 +44,7 @@ struct inquiry_data { __u8 pscan_period_mode; __u8 pscan_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; }; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cf0df1c8c933..9106354c781e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -183,7 +183,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) static void hci_init_req(struct hci_dev *hdev, unsigned long opt) { struct sk_buff *skb; - __u16 param; + __le16 param; BT_DBG("%s %ld", hdev->name, opt); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b61b4e8e36fd..eb64555d1fb3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -242,7 +242,7 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb break; status = *((__u8 *) skb->data); - setting = __le16_to_cpu(get_unaligned((__u16 *) sent)); + setting = __le16_to_cpu(get_unaligned((__le16 *) sent)); if (!status && hdev->voice_setting != setting) { hdev->voice_setting = setting; @@ -728,7 +728,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data; - __u16 *ptr; + __le16 *ptr; int i; skb_pull(skb, sizeof(*ev)); @@ -742,7 +742,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s tasklet_disable(&hdev->tx_task); - for (i = 0, ptr = (__u16 *) skb->data; i < ev->num_hndl; i++) { + for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { struct hci_conn *conn; __u16 handle, count; diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 799e448750ad..1d6d0a15c099 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -416,7 +416,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, skb->dev = (void *) hdev; if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { - u16 opcode = __le16_to_cpu(get_unaligned((u16 *)skb->data)); + u16 opcode = __le16_to_cpu(get_unaligned((__le16 *) skb->data)); u16 ogf = hci_opcode_ogf(opcode); u16 ocf = hci_opcode_ocf(opcode); -- cgit v1.2.3 From be9d122730c878baafe11e70d1436faac229f2fc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 Nov 2005 09:57:38 -0800 Subject: [Bluetooth]: Remove the usage of /proc completely This patch removes all relics of the /proc usage from the Bluetooth subsystem core and its upper layers. All the previous information are now available via /sys/class/bluetooth through appropriate functions. Signed-off-by: Marcel Holtmann Signed-off-by: David S. Miller --- include/net/bluetooth/bluetooth.h | 4 +- include/net/bluetooth/hci_core.h | 7 --- include/net/bluetooth/rfcomm.h | 2 - net/bluetooth/af_bluetooth.c | 12 +--- net/bluetooth/hci_sysfs.c | 4 +- net/bluetooth/l2cap.c | 98 +++++------------------------- net/bluetooth/rfcomm/core.c | 124 ++++++-------------------------------- net/bluetooth/rfcomm/sock.c | 90 ++++----------------------- net/bluetooth/sco.c | 92 ++++------------------------ 9 files changed, 65 insertions(+), 368 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index e42d728b1620..911ceb5cd263 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -57,8 +57,6 @@ #define BT_DBG(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __FUNCTION__ , ## arg) #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __FUNCTION__ , ## arg) -extern struct proc_dir_entry *proc_bt; - /* Connection and socket states */ enum { BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ @@ -177,4 +175,6 @@ extern int hci_sock_cleanup(void); extern int bt_sysfs_init(void); extern void bt_sysfs_cleanup(void); +extern struct class bt_class; + #endif /* __BLUETOOTH_H */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index adb94508259b..bb9f81dc8723 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -25,7 +25,6 @@ #ifndef __HCI_CORE_H #define __HCI_CORE_H -#include #include /* HCI upper protocols */ @@ -34,8 +33,6 @@ #define HCI_INIT_TIMEOUT (HZ * 10) -extern struct proc_dir_entry *proc_bt_hci; - /* HCI Core structures */ struct inquiry_data { @@ -126,10 +123,6 @@ struct hci_dev { atomic_t promisc; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc; -#endif - struct class_device class_dev; struct module *owner; diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index e656be7c001a..bbfac86734ec 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -351,6 +351,4 @@ int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); int rfcomm_init_ttys(void); void rfcomm_cleanup_ttys(void); -extern struct proc_dir_entry *proc_bt_rfcomm; - #endif /* __RFCOMM_H */ diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 03532062a46a..ea616e3fc98e 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #if defined(CONFIG_KMOD) @@ -50,10 +49,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.7" - -struct proc_dir_entry *proc_bt; -EXPORT_SYMBOL(proc_bt); +#define VERSION "2.8" /* Bluetooth sockets */ #define BT_MAX_PROTO 8 @@ -312,10 +308,6 @@ static int __init bt_init(void) { BT_INFO("Core ver %s", VERSION); - proc_bt = proc_mkdir("bluetooth", NULL); - if (proc_bt) - proc_bt->owner = THIS_MODULE; - sock_register(&bt_sock_family_ops); BT_INFO("HCI device and connection manager initialized"); @@ -334,8 +326,6 @@ static void __exit bt_exit(void) bt_sysfs_cleanup(); sock_unregister(PF_BLUETOOTH); - - remove_proc_entry("bluetooth", NULL); } subsys_initcall(bt_init); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 7856bc26accb..bd7568ac87fc 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -103,7 +103,7 @@ static void bt_release(struct class_device *cdev) kfree(hdev); } -static struct class bt_class = { +struct class bt_class = { .name = "bluetooth", .release = bt_release, #ifdef CONFIG_HOTPLUG @@ -111,6 +111,8 @@ static struct class bt_class = { #endif }; +EXPORT_SYMBOL_GPL(bt_class); + int hci_register_sysfs(struct hci_dev *hdev) { struct class_device *cdev = &hdev->class_dev; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 59b2dd36baa7..e3bb11ca4235 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -38,9 +38,8 @@ #include #include #include -#include -#include #include +#include #include #include @@ -56,7 +55,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.7" +#define VERSION "2.8" static struct proto_ops l2cap_sock_ops; @@ -2137,94 +2136,29 @@ drop: return 0; } -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *l2cap_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) { struct sock *sk; struct hlist_node *node; - loff_t l = *pos; + char *str = buf; read_lock_bh(&l2cap_sk_list.lock); - sk_for_each(sk, node, &l2cap_sk_list.head) - if (!l--) - goto found; - sk = NULL; -found: - return sk; -} + sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_pinfo *pi = l2cap_pi(sk); -static void *l2cap_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - (*pos)++; - return sk_next(e); -} + str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu, + pi->omtu, pi->link_mode); + } -static void l2cap_seq_stop(struct seq_file *seq, void *e) -{ read_unlock_bh(&l2cap_sk_list.lock); -} -static int l2cap_seq_show(struct seq_file *seq, void *e) -{ - struct sock *sk = e; - struct l2cap_pinfo *pi = l2cap_pi(sk); - - seq_printf(seq, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu, - pi->omtu, pi->link_mode); - return 0; + return (str - buf); } -static struct seq_operations l2cap_seq_ops = { - .start = l2cap_seq_start, - .next = l2cap_seq_next, - .stop = l2cap_seq_stop, - .show = l2cap_seq_show -}; - -static int l2cap_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &l2cap_seq_ops); -} - -static struct file_operations l2cap_seq_fops = { - .owner = THIS_MODULE, - .open = l2cap_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init l2cap_proc_init(void) -{ - struct proc_dir_entry *p = create_proc_entry("l2cap", S_IRUGO, proc_bt); - if (!p) - return -ENOMEM; - p->owner = THIS_MODULE; - p->proc_fops = &l2cap_seq_fops; - return 0; -} - -static void __exit l2cap_proc_cleanup(void) -{ - remove_proc_entry("l2cap", proc_bt); -} - -#else /* CONFIG_PROC_FS */ - -static int __init l2cap_proc_init(void) -{ - return 0; -} - -static void __exit l2cap_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); static struct proto_ops l2cap_sock_ops = { .family = PF_BLUETOOTH, @@ -2266,7 +2200,7 @@ static struct hci_proto l2cap_hci_proto = { static int __init l2cap_init(void) { int err; - + err = proto_register(&l2cap_proto, 0); if (err < 0) return err; @@ -2284,7 +2218,7 @@ static int __init l2cap_init(void) goto error; } - l2cap_proc_init(); + class_create_file(&bt_class, &class_attr_l2cap); BT_INFO("L2CAP ver %s", VERSION); BT_INFO("L2CAP socket layer initialized"); @@ -2298,7 +2232,7 @@ error: static void __exit l2cap_exit(void) { - l2cap_proc_cleanup(); + class_remove_file(&bt_class, &class_attr_l2cap); if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c3d56ead840c..0d89d6434136 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -35,9 +35,8 @@ #include #include #include +#include #include -#include -#include #include #include #include @@ -47,17 +46,13 @@ #include #include -#define VERSION "1.5" +#define VERSION "1.6" #ifndef CONFIG_BT_RFCOMM_DEBUG #undef BT_DBG #define BT_DBG(D...) #endif -#ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_bt_rfcomm; -#endif - static struct task_struct *rfcomm_thread; static DECLARE_MUTEX(rfcomm_sem); @@ -2001,117 +1996,32 @@ static struct hci_cb rfcomm_cb = { .encrypt_cfm = rfcomm_encrypt_cfm }; -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *rfcomm_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf) { struct rfcomm_session *s; struct list_head *pp, *p; - loff_t l = *pos; + char *str = buf; rfcomm_lock(); list_for_each(p, &session_list) { s = list_entry(p, struct rfcomm_session, list); - list_for_each(pp, &s->dlcs) - if (!l--) { - seq->private = s; - return pp; - } - } - return NULL; -} + list_for_each(pp, &s->dlcs) { + struct sock *sk = s->sock->sk; + struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list); -static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - struct rfcomm_session *s = seq->private; - struct list_head *pp, *p = e; - (*pos)++; - - if (p->next != &s->dlcs) - return p->next; - - list_for_each(p, &session_list) { - s = list_entry(p, struct rfcomm_session, list); - __list_for_each(pp, &s->dlcs) { - seq->private = s; - return pp; + str += sprintf(str, "%s %s %ld %d %d %d %d\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); } } - return NULL; -} -static void rfcomm_seq_stop(struct seq_file *seq, void *e) -{ rfcomm_unlock(); -} - -static int rfcomm_seq_show(struct seq_file *seq, void *e) -{ - struct rfcomm_session *s = seq->private; - struct sock *sk = s->sock->sk; - struct rfcomm_dlc *d = list_entry(e, struct rfcomm_dlc, list); - - seq_printf(seq, "%s %s %ld %d %d %d %d\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); - return 0; -} - -static struct seq_operations rfcomm_seq_ops = { - .start = rfcomm_seq_start, - .next = rfcomm_seq_next, - .stop = rfcomm_seq_stop, - .show = rfcomm_seq_show -}; - -static int rfcomm_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &rfcomm_seq_ops); -} - -static struct file_operations rfcomm_seq_fops = { - .owner = THIS_MODULE, - .open = rfcomm_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init rfcomm_proc_init(void) -{ - struct proc_dir_entry *p; - - proc_bt_rfcomm = proc_mkdir("rfcomm", proc_bt); - if (proc_bt_rfcomm) { - proc_bt_rfcomm->owner = THIS_MODULE; - - p = create_proc_entry("dlc", S_IRUGO, proc_bt_rfcomm); - if (p) - p->proc_fops = &rfcomm_seq_fops; - } - return 0; -} - -static void __exit rfcomm_proc_cleanup(void) -{ - remove_proc_entry("dlc", proc_bt_rfcomm); - remove_proc_entry("rfcomm", proc_bt); + return (str - buf); } -#else /* CONFIG_PROC_FS */ - -static int __init rfcomm_proc_init(void) -{ - return 0; -} - -static void __exit rfcomm_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL); /* ---- Initialization ---- */ static int __init rfcomm_init(void) @@ -2122,9 +2032,7 @@ static int __init rfcomm_init(void) kernel_thread(rfcomm_run, NULL, CLONE_KERNEL); - BT_INFO("RFCOMM ver %s", VERSION); - - rfcomm_proc_init(); + class_create_file(&bt_class, &class_attr_rfcomm_dlc); rfcomm_init_sockets(); @@ -2132,11 +2040,15 @@ static int __init rfcomm_init(void) rfcomm_init_ttys(); #endif + BT_INFO("RFCOMM ver %s", VERSION); + return 0; } static void __exit rfcomm_exit(void) { + class_remove_file(&bt_class, &class_attr_rfcomm_dlc); + hci_unregister_cb(&rfcomm_cb); /* Terminate working thread. @@ -2153,8 +2065,6 @@ static void __exit rfcomm_exit(void) #endif rfcomm_cleanup_sockets(); - - rfcomm_proc_cleanup(); } module_init(rfcomm_init); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index a2b30f0aedb7..6c34261b232e 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -42,8 +42,7 @@ #include #include #include -#include -#include +#include #include #include @@ -887,89 +886,26 @@ done: return result; } -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *rfcomm_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf) { struct sock *sk; struct hlist_node *node; - loff_t l = *pos; + char *str = buf; read_lock_bh(&rfcomm_sk_list.lock); - sk_for_each(sk, node, &rfcomm_sk_list.head) - if (!l--) - return sk; - return NULL; -} - -static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - struct sock *sk = e; - (*pos)++; - return sk_next(sk); -} + sk_for_each(sk, node, &rfcomm_sk_list.head) { + str += sprintf(str, "%s %s %d %d\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + sk->sk_state, rfcomm_pi(sk)->channel); + } -static void rfcomm_seq_stop(struct seq_file *seq, void *e) -{ read_unlock_bh(&rfcomm_sk_list.lock); -} -static int rfcomm_seq_show(struct seq_file *seq, void *e) -{ - struct sock *sk = e; - seq_printf(seq, "%s %s %d %d\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, rfcomm_pi(sk)->channel); - return 0; -} - -static struct seq_operations rfcomm_seq_ops = { - .start = rfcomm_seq_start, - .next = rfcomm_seq_next, - .stop = rfcomm_seq_stop, - .show = rfcomm_seq_show -}; - -static int rfcomm_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &rfcomm_seq_ops); + return (str - buf); } -static struct file_operations rfcomm_seq_fops = { - .owner = THIS_MODULE, - .open = rfcomm_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init rfcomm_sock_proc_init(void) -{ - struct proc_dir_entry *p = create_proc_entry("sock", S_IRUGO, proc_bt_rfcomm); - if (!p) - return -ENOMEM; - p->proc_fops = &rfcomm_seq_fops; - return 0; -} - -static void __exit rfcomm_sock_proc_cleanup(void) -{ - remove_proc_entry("sock", proc_bt_rfcomm); -} - -#else /* CONFIG_PROC_FS */ - -static int __init rfcomm_sock_proc_init(void) -{ - return 0; -} - -static void __exit rfcomm_sock_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(rfcomm, S_IRUGO, rfcomm_sock_sysfs_show, NULL); static struct proto_ops rfcomm_sock_ops = { .family = PF_BLUETOOTH, @@ -997,7 +933,7 @@ static struct net_proto_family rfcomm_sock_family_ops = { .create = rfcomm_sock_create }; -int __init rfcomm_init_sockets(void) +int __init rfcomm_init_sockets(void) { int err; @@ -1009,7 +945,7 @@ int __init rfcomm_init_sockets(void) if (err < 0) goto error; - rfcomm_sock_proc_init(); + class_create_file(&bt_class, &class_attr_rfcomm); BT_INFO("RFCOMM socket layer initialized"); @@ -1023,7 +959,7 @@ error: void __exit rfcomm_cleanup_sockets(void) { - rfcomm_sock_proc_cleanup(); + class_remove_file(&bt_class, &class_attr_rfcomm); if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) BT_ERR("RFCOMM socket layer unregistration failed"); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 997e42df115c..9cb00dc6c08c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -38,8 +38,7 @@ #include #include #include -#include -#include +#include #include #include @@ -55,7 +54,7 @@ #define BT_DBG(D...) #endif -#define VERSION "0.4" +#define VERSION "0.5" static struct proto_ops sco_sock_ops; @@ -893,91 +892,26 @@ drop: return 0; } -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *sco_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t sco_sysfs_show(struct class *dev, char *buf) { struct sock *sk; struct hlist_node *node; - loff_t l = *pos; + char *str = buf; read_lock_bh(&sco_sk_list.lock); - sk_for_each(sk, node, &sco_sk_list.head) - if (!l--) - goto found; - sk = NULL; -found: - return sk; -} - -static void *sco_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - struct sock *sk = e; - (*pos)++; - return sk_next(sk); -} + sk_for_each(sk, node, &sco_sk_list.head) { + str += sprintf(str, "%s %s %d\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + sk->sk_state); + } -static void sco_seq_stop(struct seq_file *seq, void *e) -{ read_unlock_bh(&sco_sk_list.lock); -} - -static int sco_seq_show(struct seq_file *seq, void *e) -{ - struct sock *sk = e; - seq_printf(seq, "%s %s %d\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state); - return 0; -} -static struct seq_operations sco_seq_ops = { - .start = sco_seq_start, - .next = sco_seq_next, - .stop = sco_seq_stop, - .show = sco_seq_show -}; - -static int sco_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &sco_seq_ops); + return (str - buf); } -static struct file_operations sco_seq_fops = { - .owner = THIS_MODULE, - .open = sco_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init sco_proc_init(void) -{ - struct proc_dir_entry *p = create_proc_entry("sco", S_IRUGO, proc_bt); - if (!p) - return -ENOMEM; - p->owner = THIS_MODULE; - p->proc_fops = &sco_seq_fops; - return 0; -} - -static void __exit sco_proc_cleanup(void) -{ - remove_proc_entry("sco", proc_bt); -} - -#else /* CONFIG_PROC_FS */ - -static int __init sco_proc_init(void) -{ - return 0; -} - -static void __exit sco_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(sco, S_IRUGO, sco_sysfs_show, NULL); static struct proto_ops sco_sock_ops = { .family = PF_BLUETOOTH, @@ -1035,7 +969,7 @@ static int __init sco_init(void) goto error; } - sco_proc_init(); + class_create_file(&bt_class, &class_attr_sco); BT_INFO("SCO (Voice Link) ver %s", VERSION); BT_INFO("SCO socket layer initialized"); @@ -1049,7 +983,7 @@ error: static void __exit sco_exit(void) { - sco_proc_cleanup(); + class_remove_file(&bt_class, &class_attr_sco); if (bt_sock_unregister(BTPROTO_SCO) < 0) BT_ERR("SCO socket unregistration failed"); -- cgit v1.2.3 From 37ee16ae93a3e4ae7dd51beb81d249f5f12a55c2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 19:08:05 +0000 Subject: [ARM SMP] Add core ARM support for local timers Add infrastructure for supporting per-cpu local timers to update the profiling information and update system time accounting. Signed-off-by: Russell King --- arch/arm/Kconfig | 10 ++++++++++ arch/arm/kernel/entry-armv.S | 7 +++++++ arch/arm/kernel/irq.c | 1 + arch/arm/kernel/smp.c | 34 ++++++++++++++++++++++++++++++++++ include/asm-arm/hardirq.h | 1 + include/asm-arm/smp.h | 38 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+) (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 91d5ef3397be..3bfef0934c9d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -356,6 +356,16 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. +config LOCAL_TIMERS + bool "Use local timer interrupts" + depends on SMP && n + default y + help + Enable support for local timers on SMP platforms, rather then the + legacy IPI broadcast method. Local timers allows the system + accounting to be spread across the timer interval, preventing a + "thundering herd" at every timer tick. + config PREEMPT bool "Preemptible Kernel (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a511ec5b11a3..d9fb819bf7cc 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -47,6 +47,13 @@ movne r0, sp adrne lr, 1b bne do_IPI + +#ifdef CONFIG_LOCAL_TIMERS + test_for_ltirq r0, r6, r5, lr + movne r0, sp + adrne lr, 1b + bne do_local_timer +#endif #endif .endm diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 6f86d0af7c56..d7099dbbb879 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -264,6 +264,7 @@ unlock: #endif #ifdef CONFIG_SMP show_ipi_list(p); + show_local_irqs(p); #endif seq_printf(p, "Err: %10lu\n", irq_err_count); } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index f5fc57e0fe41..77e2e9ca89fa 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -184,6 +184,11 @@ int __cpuexit __cpu_disable(void) */ migrate_irqs(); + /* + * Stop the local timer for this CPU. + */ + local_timer_stop(cpu); + /* * Flush user cache and TLB mappings, and then remove this CPU * from the vm mask set of all processes. @@ -289,6 +294,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void) */ cpu_set(cpu, cpu_online_map); + /* + * Setup local timer for this CPU. + */ + local_timer_setup(cpu); + /* * OK, it's off to the idle thread for us */ @@ -454,6 +464,18 @@ void show_ipi_list(struct seq_file *p) seq_putc(p, '\n'); } +void show_local_irqs(struct seq_file *p) +{ + unsigned int cpu; + + seq_printf(p, "LOC: "); + + for_each_present_cpu(cpu) + seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs); + + seq_putc(p, '\n'); +} + static void ipi_timer(struct pt_regs *regs) { int user = user_mode(regs); @@ -464,6 +486,18 @@ static void ipi_timer(struct pt_regs *regs) irq_exit(); } +#ifdef CONFIG_LOCAL_TIMERS +asmlinkage void do_local_timer(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + if (local_timer_ack()) { + irq_stat[cpu].local_timer_irqs++; + ipi_timer(regs); + } +} +#endif + /* * ipi_call_function - handle IPI from smp_call_function() * diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h index e5ccb6b8ff83..1cbb173bf5b1 100644 --- a/include/asm-arm/hardirq.h +++ b/include/asm-arm/hardirq.h @@ -8,6 +8,7 @@ typedef struct { unsigned int __softirq_pending; + unsigned int local_timer_irqs; } ____cacheline_aligned irq_cpustat_t; #include /* Standard mappings for irq_cpustat_t above */ diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 52e7c8d830b2..5a72e50ca9fc 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -92,4 +92,42 @@ extern void platform_cpu_die(unsigned int cpu); extern int platform_cpu_kill(unsigned int cpu); extern void platform_cpu_enable(unsigned int cpu); +#ifdef CONFIG_LOCAL_TIMERS +/* + * Setup a local timer interrupt for a CPU. + */ +extern void local_timer_setup(unsigned int cpu); + +/* + * Stop a local timer interrupt. + */ +extern void local_timer_stop(unsigned int cpu); + +/* + * Platform provides this to acknowledge a local timer IRQ + */ +extern int local_timer_ack(void); + +#else + +static inline void local_timer_setup(unsigned int cpu) +{ +} + +static inline void local_timer_stop(unsigned int cpu) +{ +} + +#endif + +/* + * show local interrupt info + */ +extern void show_local_irqs(struct seq_file *); + +/* + * Called from assembly, this is the local timer IRQ handler + */ +asmlinkage void do_local_timer(struct pt_regs *); + #endif /* ifndef __ASM_ARM_SMP_H */ -- cgit v1.2.3 From a63ae4427c6af66d6eda26e5da8fed53f8fbede3 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 8 Nov 2005 19:15:43 +0000 Subject: [ARM] 3093/1: SharpSL PCMCIA Updates for Cxx00 models Patch from Richard Purdie The Sharp SL-Cxx00 models have a combined power control for the SD and CF slot 0. This patch adds hooks to the scoop driver to allow machines to provide a custom control function for this and such a function is added for spitz/akita/borzoi. It also moves the gpio init code into the machine files as this is machine dependent and differs between some models. A couple of warnings when compiling for collie are also fixed. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/common/scoop.c | 6 -- arch/arm/mach-pxa/corgi.c | 48 +++++++++++--- arch/arm/mach-pxa/poodle.c | 32 ++++++++- arch/arm/mach-pxa/spitz.c | 95 ++++++++++++++++++++------ drivers/pcmcia/pxa2xx_sharpsl.c | 140 +++++++++++++++++++-------------------- include/asm-arm/hardware/scoop.h | 10 ++- 6 files changed, 220 insertions(+), 111 deletions(-) (limited to 'include') diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index bb4eff614413..c7fdf390cef9 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -19,12 +19,6 @@ #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr))) -/* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c - There is no easy way to link multiple scoop devices into one - single entity for the pxa2xx_pcmcia device */ -int scoop_num; -struct scoop_pcmcia_dev *scoop_devs; - struct scoop_dev { void *base; spinlock_t scoop_lock; diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index eb5f6d744a4a..100fb31b5156 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -62,6 +62,37 @@ static struct scoop_config corgi_scoop_setup = { .io_out = CORGI_SCOOP_IO_OUT, }; +struct platform_device corgiscoop_device = { + .name = "sharp-scoop", + .id = -1, + .dev = { + .platform_data = &corgi_scoop_setup, + }, + .num_resources = ARRAY_SIZE(corgi_scoop_resources), + .resource = corgi_scoop_resources, +}; + +static void corgi_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO52_nPCE_1_MD); + pxa_gpio_mode(GPIO53_nPCE_2_MD); + pxa_gpio_mode(GPIO54_pSKTSEL_MD); +} + static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { { .dev = &corgiscoop_device.dev, @@ -71,16 +102,14 @@ static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { }, }; -struct platform_device corgiscoop_device = { - .name = "sharp-scoop", - .id = -1, - .dev = { - .platform_data = &corgi_scoop_setup, - }, - .num_resources = ARRAY_SIZE(corgi_scoop_resources), - .resource = corgi_scoop_resources, +static struct scoop_pcmcia_config corgi_pcmcia_config = { + .devs = &corgi_pcmcia_scoop[0], + .num_devs = 1, + .pcmcia_init = corgi_pcmcia_init, }; +EXPORT_SYMBOL(corgiscoop_device); + /* * Corgi SSP Device @@ -294,8 +323,7 @@ static void __init corgi_init(void) pxa_set_mci_info(&corgi_mci_platform_data); pxa_set_ficp_info(&corgi_ficp_platform_data); - scoop_num = 1; - scoop_devs = &corgi_pcmcia_scoop[0]; + platform_scoop_config = &corgi_pcmcia_config; platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index ad6a13f95a62..eef3de26ad37 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -65,6 +65,27 @@ struct platform_device poodle_scoop_device = { .resource = poodle_scoop_resources, }; +static void poodle_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO52_nPCE_1_MD); + pxa_gpio_mode(GPIO53_nPCE_2_MD); + pxa_gpio_mode(GPIO54_pSKTSEL_MD); +} + static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = { { .dev = &poodle_scoop_device.dev, @@ -74,6 +95,14 @@ static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = { }, }; +static struct scoop_pcmcia_config poodle_pcmcia_config = { + .devs = &poodle_pcmcia_scoop[0], + .num_devs = 1, + .pcmcia_init = poodle_pcmcia_init, +}; + +EXPORT_SYMBOL(poodle_scoop_device); + /* LoCoMo device */ static struct resource locomo_resources[] = { @@ -268,8 +297,7 @@ static void __init poodle_init(void) pxa_set_mci_info(&poodle_mci_platform_data); pxa_set_ficp_info(&poodle_ficp_platform_data); - scoop_num = 1; - scoop_devs = &poodle_pcmcia_scoop[0]; + platform_scoop_config = &poodle_pcmcia_config; ret = platform_add_devices(devices, ARRAY_SIZE(devices)); if (ret) { diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 6c6878cd2207..4e9a699ee428 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -104,6 +104,66 @@ struct platform_device spitzscoop2_device = { .resource = spitz_scoop2_resources, }; +#define SPITZ_PWR_SD 0x01 +#define SPITZ_PWR_CF 0x02 + +/* Power control is shared with between one of the CF slots and SD */ +static void spitz_card_pwr_ctrl(int device, unsigned short new_cpr) +{ + unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR); + + if (new_cpr & 0x0007) { + set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); + if (!(cpr & 0x0002) && !(cpr & 0x0004)) + mdelay(5); + if (device == SPITZ_PWR_CF) + cpr |= 0x0002; + if (device == SPITZ_PWR_SD) + cpr |= 0x0004; + write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr); + } else { + if (device == SPITZ_PWR_CF) + cpr &= ~0x0002; + if (device == SPITZ_PWR_SD) + cpr &= ~0x0004; + write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr); + if (!(cpr & 0x0002) && !(cpr & 0x0004)) { + mdelay(1); + reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); + } + } +} + +static void spitz_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO54_nPCE_2); + GPSR(GPIO85_nPCE_1) = GPIO_bit(GPIO85_nPCE_1); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO85_nPCE_1_MD); + pxa_gpio_mode(GPIO54_nPCE_2_MD); + pxa_gpio_mode(GPIO104_pSKTSEL_MD); +} + +static void spitz_pcmcia_pwr(struct device *scoop, unsigned short cpr, int nr) +{ + /* Only need to override behaviour for slot 0 */ + if (nr == 0) + spitz_card_pwr_ctrl(SPITZ_PWR_CF, cpr); + else + write_scoop_reg(scoop, SCOOP_CPR, cpr); +} + static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = { { .dev = &spitzscoop_device.dev, @@ -117,6 +177,16 @@ static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = { }, }; +static struct scoop_pcmcia_config spitz_pcmcia_config = { + .devs = &spitz_pcmcia_scoop[0], + .num_devs = 2, + .pcmcia_init = spitz_pcmcia_init, + .power_ctrl = spitz_pcmcia_pwr, +}; + +EXPORT_SYMBOL(spitzscoop_device); +EXPORT_SYMBOL(spitzscoop2_device); + /* * Spitz SSP Device @@ -235,27 +305,14 @@ static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(in return 0; } -/* Power control is shared with one of the CF slots so we have a mess */ static void spitz_mci_setpower(struct device *dev, unsigned int vdd) { struct pxamci_platform_data* p_d = dev->platform_data; - unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR); - - if (( 1 << vdd) & p_d->ocr_mask) { - /* printk(KERN_DEBUG "%s: on\n", __FUNCTION__); */ - set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); - mdelay(2); - write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | 0x04); - } else { - /* printk(KERN_DEBUG "%s: off\n", __FUNCTION__); */ - write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr & ~0x04); - - if (!(cpr | 0x02)) { - mdelay(1); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); - } - } + if (( 1 << vdd) & p_d->ocr_mask) + spitz_card_pwr_ctrl(SPITZ_PWR_SD, 0x0004); + else + spitz_card_pwr_ctrl(SPITZ_PWR_SD, 0x0000); } static int spitz_mci_get_ro(struct device *dev) @@ -351,8 +408,8 @@ static void __init common_init(void) static void __init spitz_init(void) { - scoop_num = 2; - scoop_devs = &spitz_pcmcia_scoop[0]; + platform_scoop_config = &spitz_pcmcia_config; + spitz_bl_machinfo.set_bl_intensity = spitz_bl_set_intensity; common_init(); diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index fe5ea36e7de3..56c58831e80e 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -22,16 +22,20 @@ #include #include #include -#ifdef CONFIG_SA1100_COLLIE -#include -#else -#include -#endif #include "soc_common.h" #define NO_KEEP_VS 0x0001 +/* PCMCIA to Scoop linkage + + There is no easy way to link multiple scoop devices into one + single entity for the pxa2xx_pcmcia device so this structure + is used which is setup by the platform code +*/ +struct scoop_pcmcia_config *platform_scoop_config; +#define SCOOP_DEV platform_scoop_config->devs + static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev) { reset_scoop(scoopdev->dev); @@ -43,38 +47,16 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; -#ifndef CONFIG_SA1100_COLLIE - /* - * Setup default state of GPIO outputs - * before we enable them as outputs. - */ - GPSR(GPIO48_nPOE) = - GPIO_bit(GPIO48_nPOE) | - GPIO_bit(GPIO49_nPWE) | - GPIO_bit(GPIO50_nPIOR) | - GPIO_bit(GPIO51_nPIOW) | - GPIO_bit(GPIO52_nPCE_1) | - GPIO_bit(GPIO53_nPCE_2); - - pxa_gpio_mode(GPIO48_nPOE_MD); - pxa_gpio_mode(GPIO49_nPWE_MD); - pxa_gpio_mode(GPIO50_nPIOR_MD); - pxa_gpio_mode(GPIO51_nPIOW_MD); - pxa_gpio_mode(GPIO52_nPCE_1_MD); - pxa_gpio_mode(GPIO53_nPCE_2_MD); - pxa_gpio_mode(GPIO54_pSKTSEL_MD); - pxa_gpio_mode(GPIO55_nPREG_MD); - pxa_gpio_mode(GPIO56_nPWAIT_MD); - pxa_gpio_mode(GPIO57_nIOIS16_MD); -#endif + if (platform_scoop_config->pcmcia_init) + platform_scoop_config->pcmcia_init(); /* Register interrupts */ - if (scoop_devs[skt->nr].cd_irq >= 0) { + if (SCOOP_DEV[skt->nr].cd_irq >= 0) { struct pcmcia_irqs cd_irq; cd_irq.sock = skt->nr; - cd_irq.irq = scoop_devs[skt->nr].cd_irq; - cd_irq.str = scoop_devs[skt->nr].cd_irq_str; + cd_irq.irq = SCOOP_DEV[skt->nr].cd_irq; + cd_irq.str = SCOOP_DEV[skt->nr].cd_irq_str; ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1); if (ret) { @@ -83,19 +65,19 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) } } - skt->irq = scoop_devs[skt->nr].irq; + skt->irq = SCOOP_DEV[skt->nr].irq; return 0; } static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - if (scoop_devs[skt->nr].cd_irq >= 0) { + if (SCOOP_DEV[skt->nr].cd_irq >= 0) { struct pcmcia_irqs cd_irq; cd_irq.sock = skt->nr; - cd_irq.irq = scoop_devs[skt->nr].cd_irq; - cd_irq.str = scoop_devs[skt->nr].cd_irq_str; + cd_irq.irq = SCOOP_DEV[skt->nr].cd_irq; + cd_irq.str = SCOOP_DEV[skt->nr].cd_irq_str; soc_pcmcia_free_irqs(skt, &cd_irq, 1); } } @@ -105,9 +87,9 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { unsigned short cpr, csr; - struct device *scoop = scoop_devs[skt->nr].dev; + struct device *scoop = SCOOP_DEV[skt->nr].dev; - cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR); + cpr = read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR); write_scoop_reg(scoop, SCOOP_IRM, 0x00FF); write_scoop_reg(scoop, SCOOP_ISR, 0x0000); @@ -116,21 +98,25 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, if (csr & 0x0004) { /* card eject */ write_scoop_reg(scoop, SCOOP_CDR, 0x0000); - scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; + SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS; } - else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) { + else if (!(SCOOP_DEV[skt->nr].keep_vs & NO_KEEP_VS)) { /* keep vs1,vs2 */ write_scoop_reg(scoop, SCOOP_CDR, 0x0000); - csr |= scoop_devs[skt->nr].keep_vs; + csr |= SCOOP_DEV[skt->nr].keep_vs; } else if (cpr & 0x0003) { /* power on */ write_scoop_reg(scoop, SCOOP_CDR, 0x0000); - scoop_devs[skt->nr].keep_vs = (csr & 0x00C0); + SCOOP_DEV[skt->nr].keep_vs = (csr & 0x00C0); } else { /* card detect */ - write_scoop_reg(scoop, SCOOP_CDR, 0x0002); + if ((machine_is_spitz() || machine_is_borzoi()) && skt->nr == 1) { + write_scoop_reg(scoop, SCOOP_CDR, 0x0000); + } else { + write_scoop_reg(scoop, SCOOP_CDR, 0x0002); + } } state->detect = (csr & 0x0004) ? 0 : 1; @@ -144,7 +130,6 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, if ((cpr & 0x0080) && ((cpr & 0x8040) != 0x8040)) { printk(KERN_ERR "sharpsl_pcmcia_socket_state(): CPR=%04X, Low voltage!\n", cpr); } - } @@ -152,7 +137,7 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { unsigned long flags; - struct device *scoop = scoop_devs[skt->nr].dev; + struct device *scoop = SCOOP_DEV[skt->nr].dev; unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr; @@ -177,8 +162,13 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080; nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E; - ncpr |= (state->Vcc == 33) ? 0x0001 : - (state->Vcc == 50) ? 0x0002 : 0; + if ((machine_is_spitz() || machine_is_borzoi() || machine_is_akita()) && skt->nr == 0) { + ncpr |= (state->Vcc == 33) ? 0x0002 : + (state->Vcc == 50) ? 0x0002 : 0; + } else { + ncpr |= (state->Vcc == 33) ? 0x0001 : + (state->Vcc == 50) ? 0x0002 : 0; + } nmcr |= (state->flags&SS_IOCARD) ? 0x0010 : 0; ncpr |= (state->flags&SS_OUTPUT_ENA) ? 0x0080 : 0; nccr |= (state->flags&SS_RESET)? 0x0080: 0; @@ -190,18 +180,22 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ((skt->status&SS_WRPROT) ? 0x0008 : 0); if (!(ncpr & 0x0003)) { - scoop_devs[skt->nr].keep_rd = 0; - } else if (!scoop_devs[skt->nr].keep_rd) { + SCOOP_DEV[skt->nr].keep_rd = 0; + } else if (!SCOOP_DEV[skt->nr].keep_rd) { if (nccr & 0x0080) - scoop_devs[skt->nr].keep_rd = 1; + SCOOP_DEV[skt->nr].keep_rd = 1; else nccr |= 0x0080; } if (mcr != nmcr) write_scoop_reg(scoop, SCOOP_MCR, nmcr); - if (cpr != ncpr) - write_scoop_reg(scoop, SCOOP_CPR, ncpr); + if (cpr != ncpr) { + if (platform_scoop_config->power_ctrl) + platform_scoop_config->power_ctrl(scoop, ncpr , skt->nr); + else + write_scoop_reg(scoop, SCOOP_CPR, ncpr); + } if (ccr != nccr) write_scoop_reg(scoop, SCOOP_CCR, nccr); if (imr != nimr) @@ -214,43 +208,43 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) { - sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); + sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]); /* Enable interrupt */ - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0); - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101); - scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0); + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101); + SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS; if (machine_is_collie()) /* We need to disable SS_OUTPUT_ENA here. */ - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080); } static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { /* CF_BUS_OFF */ - sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); + sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]); if (machine_is_collie()) /* We need to disable SS_OUTPUT_ENA here. */ - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080); } static struct pcmcia_low_level sharpsl_pcmcia_ops = { - .owner = THIS_MODULE, - .hw_init = sharpsl_pcmcia_hw_init, - .hw_shutdown = sharpsl_pcmcia_hw_shutdown, - .socket_state = sharpsl_pcmcia_socket_state, - .configure_socket = sharpsl_pcmcia_configure_socket, - .socket_init = sharpsl_pcmcia_socket_init, - .socket_suspend = sharpsl_pcmcia_socket_suspend, - .first = 0, - .nr = 0, + .owner = THIS_MODULE, + .hw_init = sharpsl_pcmcia_hw_init, + .hw_shutdown = sharpsl_pcmcia_hw_shutdown, + .socket_state = sharpsl_pcmcia_socket_state, + .configure_socket = sharpsl_pcmcia_configure_socket, + .socket_init = sharpsl_pcmcia_socket_init, + .socket_suspend = sharpsl_pcmcia_socket_suspend, + .first = 0, + .nr = 0, }; -static struct platform_device *sharpsl_pcmcia_device; - #ifdef CONFIG_SA1100_COLLIE +#include "sa11xx_base.h" + int __init pcmcia_collie_init(struct device *dev) { int ret = -ENODEV; @@ -263,11 +257,13 @@ int __init pcmcia_collie_init(struct device *dev) #else +static struct platform_device *sharpsl_pcmcia_device; + static int __init sharpsl_pcmcia_init(void) { int ret; - sharpsl_pcmcia_ops.nr=scoop_num; + sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs; sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL); if (!sharpsl_pcmcia_device) return -ENOMEM; @@ -275,7 +271,7 @@ static int __init sharpsl_pcmcia_init(void) memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device)); sharpsl_pcmcia_device->name = "pxa2xx-pcmcia"; sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; - sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev; + sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev; ret = platform_device_register(sharpsl_pcmcia_device); if (ret) diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h index a8f1013930e3..d37bf7443264 100644 --- a/include/asm-arm/hardware/scoop.h +++ b/include/asm-arm/hardware/scoop.h @@ -52,8 +52,14 @@ struct scoop_pcmcia_dev { unsigned char keep_rd; }; -extern int scoop_num; -extern struct scoop_pcmcia_dev *scoop_devs; +struct scoop_pcmcia_config { + struct scoop_pcmcia_dev *devs; + int num_devs; + void (*pcmcia_init)(void); + void (*power_ctrl)(struct device *scoop, unsigned short cpr, int nr); +}; + +extern struct scoop_pcmcia_config *platform_scoop_config; void reset_scoop(struct device *dev); unsigned short set_scoop_gpio(struct device *dev, unsigned short bit); -- cgit v1.2.3 From f8c905d368c757e2c96db293a472a31abcf4b147 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 8 Nov 2005 22:43:05 +0000 Subject: [ARM] 3132/1: S3C2410 - reset on decompression error Patch from Ben Dooks Force a watchdog reset if the system fails to decompress properly. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/boot/compressed/misc.c | 6 ++++++ arch/arm/mach-s3c2410/Kconfig | 8 ++++++++ include/asm-arm/arch-s3c2410/uncompress.h | 22 ++++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 50f13eec6cd7..5ab94584baee 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -283,8 +283,14 @@ void flush_window(void) putstr("."); } +#ifndef arch_error +#define arch_error(x) +#endif + static void error(char *x) { + arch_error(x); + putstr("\n\n"); putstr(x); putstr("\n\n -- System halted"); diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index c796bcdd6158..0b9d7ca49ec1 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -121,6 +121,14 @@ config S3C2410_BOOT_WATCHDOG system resets depends on the value of PCLK. The timeout on an 200MHz s3c2410 should be about 30 seconds. +config S3C2410_BOOT_ERROR_RESET + bool "S3C2410 Reboot on decompression error" + depends on ARCH_S3C2410 + help + Say y here to use the watchdog to reset the system if the + kernel decompressor detects an error during decompression. + + comment "S3C2410 Setup" config S3C2410_DMA diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h index d7a4a8354fa9..ddd1578a7ee0 100644 --- a/include/asm-arm/arch-s3c2410/uncompress.h +++ b/include/asm-arm/arch-s3c2410/uncompress.h @@ -116,6 +116,8 @@ putstr(const char *ptr) } } +#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0) + /* CONFIG_S3C2410_BOOT_WATCHDOG * * Simple boot-time watchdog setup, to reboot the system if there is @@ -126,8 +128,6 @@ putstr(const char *ptr) #define WDOG_COUNT (0xff00) -#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0) - static inline void arch_decomp_wdog(void) { __raw_writel(WDOG_COUNT, S3C2410_WTCNT); @@ -145,6 +145,24 @@ static void arch_decomp_wdog_start(void) #define arch_decomp_wdog() #endif +#ifdef CONFIG_S3C2410_BOOT_ERROR_RESET + +static void arch_decomp_error(const char *x) +{ + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System resetting\n"); + + __raw_writel(0x4000, S3C2410_WTDAT); + __raw_writel(0x4000, S3C2410_WTCNT); + __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON); + + while(1); +} + +#define arch_error arch_decomp_error +#endif + static void error(char *err); static void -- cgit v1.2.3 From 330d57fb98a916fa8e1363846540dd420e99499a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 4 Nov 2005 10:18:40 +0000 Subject: [PATCH] Fix sysctl unregistration oops (CVE-2005-2709) You could open the /proc/sys/net/ipv4/conf// file, then wait for interface to go away, try to grab as much memory as possible in hope to hit the (kfreed) ctl_table. Then fill it with pointers to your function. Then do read from file you've opened and if you are lucky, you'll get it called as ->proc_handler() in kernel mode. So this is at least an Oops and possibly more. It does depend on an interface going away though, so less of a security risk than it would otherwise be. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/s390/appldata/appldata_base.c | 7 +- include/linux/proc_fs.h | 1 + include/linux/sysctl.h | 3 + kernel/sysctl.c | 136 +++++++++++++++++++++++++++++-------- 4 files changed, 116 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index c9f2f60cfa58..dee6ab54984d 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -592,12 +592,15 @@ int appldata_register_ops(struct appldata_ops *ops) */ void appldata_unregister_ops(struct appldata_ops *ops) { + void *table; spin_lock(&appldata_ops_lock); - unregister_sysctl_table(ops->sysctl_header); list_del(&ops->list); - kfree(ops->ctl_table); + /* at that point any incoming access will fail */ + table = ops->ctl_table; ops->ctl_table = NULL; spin_unlock(&appldata_ops_lock); + unregister_sysctl_table(ops->sysctl_header); + kfree(table); P_INFO("%s-ops unregistered!\n", ops->name); } /********************** module-ops management **************************/ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 65ceeaa30652..74488e49166d 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -66,6 +66,7 @@ struct proc_dir_entry { write_proc_t *write_proc; atomic_t count; /* use count */ int deleted; /* delete flag */ + void *set; }; struct kcore_list { diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index fc8e367f671e..fc131d6602b9 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -24,6 +24,7 @@ #include struct file; +struct completion; #define CTL_MAXNAME 10 /* how many path components do we allow in a call to sysctl? In other words, what is @@ -925,6 +926,8 @@ struct ctl_table_header { ctl_table *ctl_table; struct list_head ctl_entry; + int used; + struct completion *unregistering; }; struct ctl_table_header * register_sysctl_table(ctl_table * table, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c4f35f96884d..9990e10192e8 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -169,7 +169,7 @@ struct file_operations proc_sys_file_operations = { extern struct proc_dir_entry *proc_sys_root; -static void register_proc_table(ctl_table *, struct proc_dir_entry *); +static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *); static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); #endif @@ -992,10 +992,51 @@ static ctl_table dev_table[] = { extern void init_irq_proc (void); +static DEFINE_SPINLOCK(sysctl_lock); + +/* called under sysctl_lock */ +static int use_table(struct ctl_table_header *p) +{ + if (unlikely(p->unregistering)) + return 0; + p->used++; + return 1; +} + +/* called under sysctl_lock */ +static void unuse_table(struct ctl_table_header *p) +{ + if (!--p->used) + if (unlikely(p->unregistering)) + complete(p->unregistering); +} + +/* called under sysctl_lock, will reacquire if has to wait */ +static void start_unregistering(struct ctl_table_header *p) +{ + /* + * if p->used is 0, nobody will ever touch that entry again; + * we'll eliminate all paths to it before dropping sysctl_lock + */ + if (unlikely(p->used)) { + struct completion wait; + init_completion(&wait); + p->unregistering = &wait; + spin_unlock(&sysctl_lock); + wait_for_completion(&wait); + spin_lock(&sysctl_lock); + } + /* + * do not remove from the list until nobody holds it; walking the + * list in do_sysctl() relies on that. + */ + list_del_init(&p->ctl_entry); +} + void __init sysctl_init(void) { #ifdef CONFIG_PROC_FS - register_proc_table(root_table, proc_sys_root); + register_proc_table(root_table, proc_sys_root, &root_table_header); init_irq_proc(); #endif } @@ -1004,6 +1045,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol void __user *newval, size_t newlen) { struct list_head *tmp; + int error = -ENOTDIR; if (nlen <= 0 || nlen >= CTL_MAXNAME) return -ENOTDIR; @@ -1012,20 +1054,30 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol if (!oldlenp || get_user(old_len, oldlenp)) return -EFAULT; } + spin_lock(&sysctl_lock); tmp = &root_table_header.ctl_entry; do { struct ctl_table_header *head = list_entry(tmp, struct ctl_table_header, ctl_entry); void *context = NULL; - int error = parse_table(name, nlen, oldval, oldlenp, + + if (!use_table(head)) + continue; + + spin_unlock(&sysctl_lock); + + error = parse_table(name, nlen, oldval, oldlenp, newval, newlen, head->ctl_table, &context); kfree(context); + + spin_lock(&sysctl_lock); + unuse_table(head); if (error != -ENOTDIR) - return error; - tmp = tmp->next; - } while (tmp != &root_table_header.ctl_entry); - return -ENOTDIR; + break; + } while ((tmp = tmp->next) != &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); + return error; } asmlinkage long sys_sysctl(struct __sysctl_args __user *args) @@ -1236,12 +1288,16 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, return NULL; tmp->ctl_table = table; INIT_LIST_HEAD(&tmp->ctl_entry); + tmp->used = 0; + tmp->unregistering = NULL; + spin_lock(&sysctl_lock); if (insert_at_head) list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); else list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); #ifdef CONFIG_PROC_FS - register_proc_table(table, proc_sys_root); + register_proc_table(table, proc_sys_root, tmp); #endif return tmp; } @@ -1255,10 +1311,13 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, */ void unregister_sysctl_table(struct ctl_table_header * header) { - list_del(&header->ctl_entry); + might_sleep(); + spin_lock(&sysctl_lock); + start_unregistering(header); #ifdef CONFIG_PROC_FS unregister_proc_table(header->ctl_table, proc_sys_root); #endif + spin_unlock(&sysctl_lock); kfree(header); } @@ -1269,7 +1328,7 @@ void unregister_sysctl_table(struct ctl_table_header * header) #ifdef CONFIG_PROC_FS /* Scan the sysctl entries in table and add them all into /proc */ -static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) +static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) { struct proc_dir_entry *de; int len; @@ -1305,13 +1364,14 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) de = create_proc_entry(table->procname, mode, root); if (!de) continue; + de->set = set; de->data = (void *) table; if (table->proc_handler) de->proc_fops = &proc_sys_file_operations; } table->de = de; if (de->mode & S_IFDIR) - register_proc_table(table->child, de); + register_proc_table(table->child, de, set); } } @@ -1336,6 +1396,13 @@ static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root continue; } + /* + * In any case, mark the entry as goner; we'll keep it + * around if it's busy, but we'll know to do nothing with + * its fields. We are under sysctl_lock here. + */ + de->data = NULL; + /* Don't unregister proc entries that are still being used.. */ if (atomic_read(&de->count)) continue; @@ -1349,27 +1416,38 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf, size_t count, loff_t *ppos) { int op; - struct proc_dir_entry *de; + struct proc_dir_entry *de = PDE(file->f_dentry->d_inode); struct ctl_table *table; size_t res; - ssize_t error; - - de = PDE(file->f_dentry->d_inode); - if (!de || !de->data) - return -ENOTDIR; - table = (struct ctl_table *) de->data; - if (!table || !table->proc_handler) - return -ENOTDIR; - op = (write ? 002 : 004); - if (ctl_perm(table, op)) - return -EPERM; + ssize_t error = -ENOTDIR; - res = count; - - error = (*table->proc_handler) (table, write, file, buf, &res, ppos); - if (error) - return error; - return res; + spin_lock(&sysctl_lock); + if (de && de->data && use_table(de->set)) { + /* + * at that point we know that sysctl was not unregistered + * and won't be until we finish + */ + spin_unlock(&sysctl_lock); + table = (struct ctl_table *) de->data; + if (!table || !table->proc_handler) + goto out; + error = -EPERM; + op = (write ? 002 : 004); + if (ctl_perm(table, op)) + goto out; + + /* careful: calling conventions are nasty here */ + res = count; + error = (*table->proc_handler)(table, write, file, + buf, &res, ppos); + if (!error) + error = res; + out: + spin_lock(&sysctl_lock); + unuse_table(de->set); + } + spin_unlock(&sysctl_lock); + return error; } static int proc_opensys(struct inode *inode, struct file *file) -- cgit v1.2.3 From e3305626e0985faa8796f1f4e5a99c1f40bfa70e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 9 Nov 2005 01:01:04 -0500 Subject: ieee80211: cleanup crypto list handling, other minor cleanups. --- include/net/ieee80211_crypt.h | 1 + net/ieee80211/ieee80211_crypt.c | 152 +++++++++++----------------------------- 2 files changed, 42 insertions(+), 111 deletions(-) (limited to 'include') diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h index 0a1c2d82ca4b..225fc751d464 100644 --- a/include/net/ieee80211_crypt.h +++ b/include/net/ieee80211_crypt.h @@ -31,6 +31,7 @@ enum { struct ieee80211_crypto_ops { const char *name; + struct list_head list; /* init new crypto context (e.g., allocate private data space, * select IV, etc.); returns NULL on failure or pointer to allocated diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c index 20cc580a07e0..ecc9bb196abc 100644 --- a/net/ieee80211/ieee80211_crypt.c +++ b/net/ieee80211/ieee80211_crypt.c @@ -11,15 +11,14 @@ * */ -#include +#include #include #include #include -#include -#include - +#include #include + MODULE_AUTHOR("Jouni Malinen"); MODULE_DESCRIPTION("HostAP crypto"); MODULE_LICENSE("GPL"); @@ -29,32 +28,20 @@ struct ieee80211_crypto_alg { struct ieee80211_crypto_ops *ops; }; -struct ieee80211_crypto { - struct list_head algs; - spinlock_t lock; -}; - -static struct ieee80211_crypto *hcrypt; +static LIST_HEAD(ieee80211_crypto_algs); +static DEFINE_SPINLOCK(ieee80211_crypto_lock); void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) { - struct list_head *ptr, *n; - struct ieee80211_crypt_data *entry; + struct ieee80211_crypt_data *entry, *next; unsigned long flags; spin_lock_irqsave(&ieee->lock, flags); - - if (list_empty(&ieee->crypt_deinit_list)) - goto unlock; - - for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; - ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { - entry = list_entry(ptr, struct ieee80211_crypt_data, list); - + list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) { if (atomic_read(&entry->refcnt) != 0 && !force) continue; - list_del(ptr); + list_del(&entry->list); if (entry->ops) { entry->ops->deinit(entry->priv); @@ -62,7 +49,6 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) } kfree(entry); } - unlock: spin_unlock_irqrestore(&ieee->lock, flags); } @@ -125,9 +111,6 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) unsigned long flags; struct ieee80211_crypto_alg *alg; - if (hcrypt == NULL) - return -1; - alg = kmalloc(sizeof(*alg), GFP_KERNEL); if (alg == NULL) return -ENOMEM; @@ -135,9 +118,9 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) memset(alg, 0, sizeof(*alg)); alg->ops = ops; - spin_lock_irqsave(&hcrypt->lock, flags); - list_add(&alg->list, &hcrypt->algs); - spin_unlock_irqrestore(&hcrypt->lock, flags); + spin_lock_irqsave(&ieee80211_crypto_lock, flags); + list_add(&alg->list, &ieee80211_crypto_algs); + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", ops->name); @@ -147,64 +130,49 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) { + struct ieee80211_crypto_alg *alg; unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *del_alg = NULL; - - if (hcrypt == NULL) - return -1; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *)ptr; - if (alg->ops == ops) { - list_del(&alg->list); - del_alg = alg; - break; - } - } - spin_unlock_irqrestore(&hcrypt->lock, flags); - if (del_alg) { - printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " - "'%s'\n", ops->name); - kfree(del_alg); + spin_lock_irqsave(&ieee80211_crypto_lock, flags); + list_for_each_entry(alg, &ieee80211_crypto_algs, list) { + if (alg->ops == ops) + goto found; } - - return del_alg ? 0 : -1; + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + return -EINVAL; + + found: + printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " + "'%s'\n", ops->name); + list_del(&alg->list); + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + kfree(alg); + return 0; } struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) { + struct ieee80211_crypto_alg *alg; unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *found_alg = NULL; - - if (hcrypt == NULL) - return NULL; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *)ptr; - if (strcmp(alg->ops->name, name) == 0) { - found_alg = alg; - break; - } + + spin_lock_irqsave(&ieee80211_crypto_lock, flags); + list_for_each_entry(alg, &ieee80211_crypto_algs, list) { + if (strcmp(alg->ops->name, name) == 0) + goto found; } - spin_unlock_irqrestore(&hcrypt->lock, flags); + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + return NULL; - if (found_alg) - return found_alg->ops; - else - return NULL; + found: + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + return alg->ops; } static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; } + static void ieee80211_crypt_null_deinit(void *priv) { } @@ -213,56 +181,18 @@ static struct ieee80211_crypto_ops ieee80211_crypt_null = { .name = "NULL", .init = ieee80211_crypt_null_init, .deinit = ieee80211_crypt_null_deinit, - .encrypt_mpdu = NULL, - .decrypt_mpdu = NULL, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = NULL, - .get_key = NULL, - .extra_mpdu_prefix_len = 0, - .extra_mpdu_postfix_len = 0, .owner = THIS_MODULE, }; static int __init ieee80211_crypto_init(void) { - int ret = -ENOMEM; - - hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); - if (!hcrypt) - goto out; - - memset(hcrypt, 0, sizeof(*hcrypt)); - INIT_LIST_HEAD(&hcrypt->algs); - spin_lock_init(&hcrypt->lock); - - ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); - if (ret < 0) { - kfree(hcrypt); - hcrypt = NULL; - } - out: - return ret; + return ieee80211_register_crypto_ops(&ieee80211_crypt_null); } static void __exit ieee80211_crypto_deinit(void) { - struct list_head *ptr, *n; - - if (hcrypt == NULL) - return; - - for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; - ptr = n, n = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *)ptr; - list_del(ptr); - printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " - "'%s' (deinit)\n", alg->ops->name); - kfree(alg); - } - - kfree(hcrypt); + ieee80211_unregister_crypto_ops(&ieee80211_crypt_null); + BUG_ON(!list_empty(&ieee80211_crypto_algs)); } EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); -- cgit v1.2.3 From 2a98beb6390aef8fad85103ea25b3b1ace8015b5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 9 Nov 2005 10:50:29 +0000 Subject: [ARM SMP] Add local timer support for Realview MPcore Add platform specific parts for local timer support for the Realview board. Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm/mach-realview/Makefile | 1 + arch/arm/mach-realview/core.c | 2 +- arch/arm/mach-realview/localtimer.c | 130 ++++++++++++++++++++++++++++ arch/arm/mach-realview/platsmp.c | 5 ++ include/asm-arm/arch-realview/entry-macro.S | 11 +++ include/asm-arm/arch-realview/irqs.h | 3 + include/asm-arm/arch-realview/platform.h | 5 +- 8 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-realview/localtimer.c (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3bfef0934c9d..ec77721507cb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -358,7 +358,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && n + depends on SMP && REALVIEW_MPCORE default y help Enable support for local timers on SMP platforms, rather then the diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 011a85c10627..a6a40dac26a9 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -5,3 +5,4 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 4ea60d8b6e36..e2c6fa23d3cd 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -550,7 +550,7 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_reg timer_tick(regs); -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS) smp_send_timer(); update_process_times(user_mode(regs)); #endif diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c new file mode 100644 index 000000000000..5e917e37d095 --- /dev/null +++ b/arch/arm/mach-realview/localtimer.c @@ -0,0 +1,130 @@ +/* + * linux/arch/arm/mach-realview/localtimer.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * 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 "core.h" + +#define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \ + ((cpu) * REALVIEW_TWD_SIZE)) + +static unsigned long mpcore_timer_rate; + +/* + * local_timer_ack: checks for a local timer interrupt. + * + * If a local timer interrupt has occured, acknowledge and return 1. + * Otherwise, return 0. + */ +int local_timer_ack(void) +{ + void __iomem *base = TWD_BASE(smp_processor_id()); + + if (__raw_readl(base + TWD_TIMER_INTSTAT)) { + __raw_writel(1, base + TWD_TIMER_INTSTAT); + return 1; + } + + return 0; +} + +void __cpuinit local_timer_setup(unsigned int cpu) +{ + void __iomem *base = TWD_BASE(cpu); + unsigned int load, offset; + u64 waitjiffies; + unsigned int count; + + /* + * If this is the first time round, we need to work out how fast + * the timer ticks + */ + if (mpcore_timer_rate == 0) { + printk("Calibrating local timer... "); + + /* Wait for a tick to start */ + waitjiffies = get_jiffies_64() + 1; + + while (get_jiffies_64() < waitjiffies) + udelay(10); + + /* OK, now the tick has started, let's get the timer going */ + waitjiffies += 5; + + /* enable, no interrupt or reload */ + __raw_writel(0x1, base + TWD_TIMER_CONTROL); + + /* maximum value */ + __raw_writel(0xFFFFFFFFU, base + TWD_TIMER_COUNTER); + + while (get_jiffies_64() < waitjiffies) + udelay(10); + + count = __raw_readl(base + TWD_TIMER_COUNTER); + + mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); + + printk("%lu.%02luMHz.\n", mpcore_timer_rate / 1000000, + (mpcore_timer_rate / 100000) % 100); + } + + load = mpcore_timer_rate / HZ; + + __raw_writel(load, base + TWD_TIMER_LOAD); + __raw_writel(0x7, base + TWD_TIMER_CONTROL); + + /* + * Now maneuver our local tick into the right part of the jiffy. + * Start by working out where within the tick our local timer + * interrupt should go. + */ + offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1); + + /* + * gettimeoffset() will return a number of us since the last tick. + * Convert this number of us to a local timer tick count. + * Be careful of integer overflow whilst keeping maximum precision. + * + * with HZ=100 and 1MHz (fpga) ~ 1GHz processor: + * load = 1 ~ 10,000 + * mpcore_timer_rate/10000 = 100 ~ 100,000 + * + * so the multiply value will be less than 10^9 always. + */ + load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100; + + /* Add on our offset to get the load value */ + load = (load + offset) % (mpcore_timer_rate / HZ); + + __raw_writel(load, base + TWD_TIMER_COUNTER); + + /* Make sure our local interrupt controller has this enabled */ + __raw_writel(1 << IRQ_LOCALTIMER, + __io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET); +} + +/* + * take a local timer down + */ +void __cpuexit local_timer_stop(unsigned int cpu) +{ + __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); +} diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 09b35f62247a..0c7d4ac9a7b3 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -174,6 +174,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (max_cpus > ncores) max_cpus = ncores; + /* + * Enable the local timer for primary CPU + */ + local_timer_setup(cpu); + /* * Initialise the possible/present maps. * cpu_possible_map describes the set of CPUs which may be present diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S index 4df469bf42e2..6288fad0dc41 100644 --- a/include/asm-arm/arch-realview/entry-macro.S +++ b/include/asm-arm/arch-realview/entry-macro.S @@ -61,3 +61,14 @@ strcc \irqstat, [\base, #GIC_CPU_EOI] cmpcs \irqnr, \irqnr .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h index ff376494e5b1..c16223c9588d 100644 --- a/include/asm-arm/arch-realview/irqs.h +++ b/include/asm-arm/arch-realview/irqs.h @@ -21,6 +21,9 @@ #include +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 + /* * IRQ interrupts definitions are the same the INT definitions * held within platform.h diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index aef9b36b3c37..18d7c18b738c 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -209,6 +209,8 @@ #else #define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ #define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_TWD_BASE 0x10100700 +#define REALVIEW_TWD_SIZE 0x00000100 #define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ #endif #define REALVIEW_SMC_BASE 0x10080000 /* SMC */ @@ -305,9 +307,6 @@ #define INT_TSPENINT 30 /* Touchscreen pen */ #define INT_TSKPADINT 31 /* Touchscreen keypad */ #else -#define INT_LOCALTIMER 29 -#define INT_LOCALWDOG 30 - #define INT_AACI 0 #define INT_TIMERINT0_1 1 #define INT_TIMERINT2_3 2 -- cgit v1.2.3 From 59d1ff3bfb56d9b8cf3ec864857e6a4dfd9d2dba Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 9 Nov 2005 15:04:22 +0000 Subject: [ARM] Clean up save_and_disable_irqs macro and allow use of ARMv6 CPSID save_and_disable_irqs does not need to use mov + msr (which was introduced to work around a documentation bug which was propagated into binutils.) Use msr with an immediate constant, and if we're building for ARMv6 or later, use the new CPSID instruction. Signed-off-by: Russell King --- arch/arm/lib/bitops.h | 4 ++-- include/asm-arm/assembler.h | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index f35d91fbe117..b8c14e936697 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -34,7 +34,7 @@ and r2, r0, #7 mov r3, #1 mov r3, r3, lsl r2 - save_and_disable_irqs ip, r2 + save_and_disable_irqs ip ldrb r2, [r1, r0, lsr #3] \instr r2, r2, r3 strb r2, [r1, r0, lsr #3] @@ -54,7 +54,7 @@ add r1, r1, r0, lsr #3 and r3, r0, #7 mov r0, #1 - save_and_disable_irqs ip, r2 + save_and_disable_irqs ip ldrb r2, [r1] tst r2, r0, lsl r3 \instr r2, r2, r0, lsl r3 diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h index 69a28f96bee2..f31ac92b6c7f 100644 --- a/include/asm-arm/assembler.h +++ b/include/asm-arm/assembler.h @@ -83,10 +83,13 @@ * Save the current IRQ state and disable IRQs. Note that this macro * assumes FIQs are enabled, and that the processor is in SVC mode. */ - .macro save_and_disable_irqs, oldcpsr, temp + .macro save_and_disable_irqs, oldcpsr mrs \oldcpsr, cpsr - mov \temp, #PSR_I_BIT | MODE_SVC - msr cpsr_c, \temp +#if __LINUX_ARM_ARCH__ >= 6 + cpsid i +#else + msr cpsr_c, #PSR_I_BIT | MODE_SVC +#endif .endm /* -- cgit v1.2.3 From 861e37ad5969f764574722f4cfc0734511cbac7f Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Wed, 9 Nov 2005 15:15:10 +0000 Subject: [ARM] 3057/1: Add memory control method to support OneNAND sync burst read Patch from Kyungmin Park This patch is required for OneNAND MTD to passing the OneNAND sync. burst read Signed-off-by: Kyungmin Park Signed-off-by: Russell King --- include/asm-arm/mach/flash.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/asm-arm/mach/flash.h b/include/asm-arm/mach/flash.h index cd57436d9874..05b029ef6371 100644 --- a/include/asm-arm/mach/flash.h +++ b/include/asm-arm/mach/flash.h @@ -11,6 +11,7 @@ #define ASMARM_MACH_FLASH_H struct mtd_partition; +struct mtd_info; /* * map_name: the map probe function name @@ -19,6 +20,7 @@ struct mtd_partition; * init: method called at driver/device initialisation * exit: method called at driver/device removal * set_vpp: method called to enable or disable VPP + * mmcontrol: method called to enable or disable Sync. Burst Read in OneNAND * parts: optional array of mtd_partitions for static partitioning * nr_parts: number of mtd_partitions for static partitoning */ @@ -29,6 +31,7 @@ struct flash_platform_data { int (*init)(void); void (*exit)(void); void (*set_vpp)(int on); + void (*mmcontrol)(struct mtd_info *mtd, int sync_read); struct mtd_partition *parts; unsigned int nr_parts; }; -- cgit v1.2.3 From 90d45d17f3e68608ac7ba8fc3d7acce022a19c8e Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 8 Nov 2005 21:34:24 -0800 Subject: [PATCH] cpu hotplug: fix locking in cpufreq drivers When calling target drivers to set frequency, we take cpucontrol lock. When we modified the code to accomodate CPU hotplug, there was an attempt to take a double lock of cpucontrol leading to a deadlock. Since the current thread context is already holding the cpucontrol lock, we dont need to make another attempt to acquire it. Now we leave a trace in current->flags indicating current thread already is under cpucontrol lock held, so we dont attempt to do this another time. Thanks to Andrew Morton for the beating:-) From: Brice Goglin Build fix (akpm: this patch is still unpleasant. Ashok continues to look for a cleaner solution, doesn't he? ;)) Signed-off-by: Ashok Raj Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 24 ++++++++++-------------- include/linux/cpu.h | 5 +++++ include/linux/sched.h | 1 + kernel/cpu.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 25acf478c9e8..23a63207d747 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -38,7 +38,6 @@ static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static DEFINE_SPINLOCK(cpufreq_driver_lock); - /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); @@ -1115,24 +1114,21 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, int retval = -EINVAL; /* - * Converted the lock_cpu_hotplug to preempt_disable() - * and preempt_enable(). This is a bit kludgy and relies on how cpu - * hotplug works. All we need is a guarantee that cpu hotplug won't make - * progress on any cpu. Once we do preempt_disable(), this would ensure - * that hotplug threads don't get onto this cpu, thereby delaying - * the cpu remove process. - * - * We removed the lock_cpu_hotplug since we need to call this function - * via cpu hotplug callbacks, which result in locking the cpu hotplug - * thread itself. Agree this is not very clean, cpufreq community - * could improve this if required. - Ashok Raj + * If we are already in context of hotplug thread, we dont need to + * acquire the hotplug lock. Otherwise acquire cpucontrol to prevent + * hotplug from removing this cpu that we are working on. */ - preempt_disable(); + if (!current_in_cpu_hotplug()) + lock_cpu_hotplug(); + dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu, target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); - preempt_enable(); + + if (!current_in_cpu_hotplug()) + unlock_cpu_hotplug(); + return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 1f7b2c097503..43c44530ef9d 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -42,6 +42,7 @@ struct notifier_block; /* Need to know about CPUs going up/down? */ extern int register_cpu_notifier(struct notifier_block *nb); extern void unregister_cpu_notifier(struct notifier_block *nb); +extern int current_in_cpu_hotplug(void); int cpu_up(unsigned int cpu); @@ -54,6 +55,10 @@ static inline int register_cpu_notifier(struct notifier_block *nb) static inline void unregister_cpu_notifier(struct notifier_block *nb) { } +static inline int current_in_cpu_hotplug(void) +{ + return 0; +} #endif /* CONFIG_SMP */ extern struct sysdev_class cpu_sysdev_class; diff --git a/include/linux/sched.h b/include/linux/sched.h index 03b68a7b4b82..2bbf968b23d9 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -909,6 +909,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ #define PF_RANDOMIZE 0x00800000 /* randomize virtual address space */ +#define PF_HOTPLUG_CPU 0x01000000 /* Currently performing CPU hotplug */ /* * Only the _current_ task can read/write to tsk->flags, but other diff --git a/kernel/cpu.c b/kernel/cpu.c index 3619e939182e..d61ba88f34e5 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -21,6 +21,24 @@ EXPORT_SYMBOL_GPL(cpucontrol); static struct notifier_block *cpu_chain; +/* + * Used to check by callers if they need to acquire the cpucontrol + * or not to protect a cpu from being removed. Its sometimes required to + * call these functions both for normal operations, and in response to + * a cpu being added/removed. If the context of the call is in the same + * thread context as a CPU hotplug thread, we dont need to take the lock + * since its already protected + * check drivers/cpufreq/cpufreq.c for its usage - Ashok Raj + */ + +int current_in_cpu_hotplug(void) +{ + return (current->flags & PF_HOTPLUG_CPU); +} + +EXPORT_SYMBOL_GPL(current_in_cpu_hotplug); + + /* Need to know about CPUs going up/down? */ int register_cpu_notifier(struct notifier_block *nb) { @@ -94,6 +112,13 @@ int cpu_down(unsigned int cpu) goto out; } + /* + * Leave a trace in current->flags indicating we are already in + * process of performing CPU hotplug. Callers can check if cpucontrol + * is already acquired by current thread, and if so not cause + * a dead lock by not acquiring the lock + */ + current->flags |= PF_HOTPLUG_CPU; err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, (void *)(long)cpu); if (err == NOTIFY_BAD) { @@ -146,6 +171,7 @@ out_thread: out_allowed: set_cpus_allowed(current, old_allowed); out: + current->flags &= ~PF_HOTPLUG_CPU; unlock_cpu_hotplug(); return err; } @@ -163,6 +189,12 @@ int __devinit cpu_up(unsigned int cpu) ret = -EINVAL; goto out; } + + /* + * Leave a trace in current->flags indicating we are already in + * process of performing CPU hotplug. + */ + current->flags |= PF_HOTPLUG_CPU; ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); if (ret == NOTIFY_BAD) { printk("%s: attempt to bring up CPU %u failed\n", @@ -185,6 +217,7 @@ out_notify: if (ret != 0) notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); out: + current->flags &= ~PF_HOTPLUG_CPU; up(&cpucontrol); return ret; } -- cgit v1.2.3 From 78b331213ec738ee4c1218034d6eec17293b3aed Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 8 Nov 2005 21:34:37 -0800 Subject: [PATCH] ppc32: Update MPC834x platform to work with new phylib MPC834x uses the gianfar network driver which now uses the new phylib. We need to update the platform code to create a gianfar platform MDIO bus and pass the right intializations to the gianfar driver to make things work again. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/configs/mpc834x_sys_defconfig | 431 ++++++++++++++++++++++++--------- arch/ppc/platforms/83xx/mpc834x_sys.c | 23 +- arch/ppc/syslib/mpc83xx_devices.c | 12 +- arch/ppc/syslib/mpc83xx_sys.c | 24 +- include/asm-ppc/mpc83xx.h | 1 + 5 files changed, 353 insertions(+), 138 deletions(-) (limited to 'include') diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig index 4a5522ca8207..673dc64ebcb1 100644 --- a/arch/ppc/configs/mpc834x_sys_defconfig +++ b/arch/ppc/configs/mpc834x_sys_defconfig @@ -1,16 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-rc4 -# Thu Feb 17 16:12:23 2005 +# Linux kernel version: 2.6.14 +# Mon Nov 7 15:38:29 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y # # Code maturity level options @@ -18,23 +19,28 @@ CONFIG_GENERIC_NVRAM=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y # CONFIG_EPOLL is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -44,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -59,44 +66,90 @@ CONFIG_6xx=y # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set +# CONFIG_E200 is not set # CONFIG_E500 is not set +CONFIG_PPC_FPU=y +# CONFIG_KEXEC is not set # CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set CONFIG_PPC_GEN550=y -CONFIG_83xx=y - -# -# Freescale 83xx options -# -CONFIG_MPC834x_SYS=y -CONFIG_MPC834x=y CONFIG_PPC_STD_MMU=y # # Platform options # +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_APUS is not set +# CONFIG_KATANA is not set +# CONFIG_WILLOW is not set +# CONFIG_CPCI690 is not set +# CONFIG_POWERPMC250 is not set +# CONFIG_CHESTNUT is not set +# CONFIG_SPRUCE is not set +# CONFIG_HDPU is not set +# CONFIG_EV64260 is not set +# CONFIG_LOPEC is not set +# CONFIG_MVME5100 is not set +# CONFIG_PPLUS is not set +# CONFIG_PRPMC750 is not set +# CONFIG_PRPMC800 is not set +# CONFIG_SANDPOINT is not set +# CONFIG_RADSTONE_PPC7D is not set +# CONFIG_PAL4 is not set +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_PQ2FADS is not set +# CONFIG_LITE5200 is not set +CONFIG_MPC834x_SYS=y +# CONFIG_EV64360 is not set +CONFIG_83xx=y +CONFIG_MPC834x=y # CONFIG_SMP is not set -# CONFIG_PREEMPT is not set # CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y # # Bus options # CONFIG_GENERIC_ISA_DMA=y -# CONFIG_PCI is not set -# CONFIG_PCI_DOMAINS is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_MPC83xx_PCI2 is not set +CONFIG_PCI_LEGACY_PROC=y # # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set -# -# PC-card bridges -# - # # Advanced setup # @@ -111,6 +164,75 @@ CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE=0x80000000 CONFIG_BOOT_LOAD=0x00800000 +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + # # Device Drivers # @@ -122,6 +244,11 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + # # Memory Technology Devices (MTD) # @@ -140,15 +267,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # Block devices # # CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set @@ -159,6 +290,11 @@ CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ATA_OVER_ETH is not set # @@ -169,6 +305,7 @@ CONFIG_IOSCHED_CFQ=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -179,110 +316,116 @@ CONFIG_IOSCHED_CFQ=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support # +# CONFIG_IEEE1394 is not set # # I2O device support # +# CONFIG_I2O is not set # # Macintosh device drivers # # -# Networking support +# Network device support # -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # -# SCTP Configuration (EXPERIMENTAL) +# ARCnet devices # -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set +# CONFIG_ARCNET is not set # -# QoS and/or fair queueing +# PHY device support # -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set +CONFIG_PHYLIB=y # -# Network testing +# MII PHY device drivers # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set # # Ethernet (1000 Mbit) # +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set CONFIG_GIANFAR=y # CONFIG_GFAR_NAPI is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices # +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -293,10 +436,14 @@ CONFIG_GIANFAR=y # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -322,14 +469,6 @@ CONFIG_INPUT=y # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set - # # Input Device Drivers # @@ -339,6 +478,12 @@ CONFIG_SOUND_GAMEPORT=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + # # Character devices # @@ -358,6 +503,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -376,6 +522,7 @@ CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver @@ -384,6 +531,12 @@ CONFIG_GEN_RTC=y # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + # # I2C support # @@ -400,23 +553,68 @@ CONFIG_I2C_CHARDEV=y # # I2C Hardware Bus support # -# CONFIG_I2C_ISA is not set +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support # -# CONFIG_I2C_SENSOR is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set # CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set @@ -427,33 +625,26 @@ CONFIG_I2C_MPC=y # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# Dallas's 1-wire bus +# Misc devices # -# CONFIG_W1 is not set # -# Misc devices +# Multimedia Capabilities Port drivers # # @@ -479,11 +670,12 @@ CONFIG_I2C_MPC=y # # USB support # -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # @@ -501,11 +693,16 @@ CONFIG_I2C_MPC=y # # CONFIG_INFINIBAND is not set +# +# SN Devices +# + # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set @@ -515,17 +712,16 @@ CONFIG_JBD=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -546,12 +742,10 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -580,6 +774,7 @@ CONFIG_NFS_FS=y # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -588,6 +783,7 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -614,6 +810,7 @@ CONFIG_PARTITION_ADVANCED=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set @@ -625,7 +822,9 @@ CONFIG_CRC32=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SERIAL_TEXT_DEBUG is not set # diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 79b3f533d0a3..98edc75f4105 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -51,6 +51,9 @@ #include +static const char *GFAR_PHY_0 = "phy0:0"; +static const char *GFAR_PHY_1 = "phy0:1"; + #ifndef CONFIG_PCI unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -97,6 +100,7 @@ mpc834x_sys_setup_arch(void) bd_t *binfo = (bd_t *) __res; unsigned int freq; struct gianfar_platform_data *pdata; + struct gianfar_mdio_data *mdata; /* get the core frequency */ freq = binfo->bi_intfreq; @@ -111,24 +115,27 @@ mpc834x_sys_setup_arch(void) #endif mpc83xx_early_serial_map(); + /* setup the board related info for the MDIO bus */ + mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC83xx_MDIO); + + mdata->irq[0] = MPC83xx_IRQ_EXT1; + mdata->irq[1] = MPC83xx_IRQ_EXT2; + mdata->irq[2] = -1; + mdata->irq[31] = -1; + mdata->paddr += binfo->bi_immr_base; + /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->interruptPHY = MPC83xx_IRQ_EXT1; - pdata->phyid = 0; - /* fixup phy address */ - pdata->phy_reg_addr += binfo->bi_immr_base; + pdata->bus_id = GFAR_PHY_0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->interruptPHY = MPC83xx_IRQ_EXT2; - pdata->phyid = 1; - /* fixup phy address */ - pdata->phy_reg_addr += binfo->bi_immr_base; + pdata->bus_id = GFAR_PHY_1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index dbf8acac507f..f43fbf9a9389 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -27,18 +27,20 @@ * what IMMRBAR is, will get fixed up by mach_mpc83xx_fixup */ +struct gianfar_mdio_data mpc83xx_mdio_pdata = { + .paddr = 0x24520, +}; + static struct gianfar_platform_data mpc83xx_tsec1_pdata = { .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON | FSL_GIANFAR_DEV_HAS_MULTI_INTR, - .phy_reg_addr = 0x24000, }; static struct gianfar_platform_data mpc83xx_tsec2_pdata = { .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON | FSL_GIANFAR_DEV_HAS_MULTI_INTR, - .phy_reg_addr = 0x24000, }; static struct fsl_i2c_platform_data mpc83xx_fsl_i2c1_pdata = { @@ -220,6 +222,12 @@ struct platform_device ppc_sys_platform_devices[] = { }, }, }, + [MPC83xx_MDIO] = { + .name = "fsl-gianfar_mdio", + .id = 0, + .dev.platform_data = &mpc83xx_mdio_pdata, + .num_resources = 0, + }, }; static int __init mach_mpc83xx_fixup(struct platform_device *pdev) diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index 29aa63350025..da743446789b 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c @@ -24,72 +24,72 @@ struct ppc_sys_spec ppc_sys_specs[] = { .ppc_sys_name = "8349E", .mask = 0xFFFF0000, .value = 0x80500000, - .num_devices = 8, + .num_devices = 9, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8349", .mask = 0xFFFF0000, .value = 0x80510000, - .num_devices = 7, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8347E", .mask = 0xFFFF0000, .value = 0x80520000, - .num_devices = 8, + .num_devices = 9, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8347", .mask = 0xFFFF0000, .value = 0x80530000, - .num_devices = 7, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8343E", .mask = 0xFFFF0000, .value = 0x80540000, - .num_devices = 7, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2, - MPC83xx_USB2_DR, + MPC83xx_USB2_DR, MPC83xx_MDIO }, }, { .ppc_sys_name = "8343", .mask = 0xFFFF0000, .value = 0x80550000, - .num_devices = 6, + .num_devices = 7, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, - MPC83xx_USB2_DR, + MPC83xx_USB2_DR, MPC83xx_MDIO }, }, { /* default match */ diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index bb1b0576c947..ce212201db2a 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h @@ -107,6 +107,7 @@ enum ppc_sys_devices { MPC83xx_SEC2, MPC83xx_USB2_DR, MPC83xx_USB2_MPH, + MPC83xx_MDIO, }; #endif /* CONFIG_83xx */ -- cgit v1.2.3 From a31751e04ea738acc8042e5aa1a825901aa7b97f Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 8 Nov 2005 21:34:38 -0800 Subject: [PATCH] ppc32: fix perf_irq extern on e500 Fixes e500 build and cleans up traps.c by moving perf_irq extern to pmc.h. Signed-off-by: Matt Porter Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/traps.c | 4 ---- include/asm-powerpc/pmc.h | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 32f215825e8d..0578f8387603 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -887,10 +887,6 @@ void altivec_unavailable_exception(struct pt_regs *regs) die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); } -#ifdef CONFIG_PPC64 -extern perf_irq_t perf_irq; -#endif - #if defined(CONFIG_PPC64) || defined(CONFIG_E500) void performance_monitor_exception(struct pt_regs *regs) { diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h index 2f3c3fc2b796..5f41f3a2b293 100644 --- a/include/asm-powerpc/pmc.h +++ b/include/asm-powerpc/pmc.h @@ -22,6 +22,7 @@ #include typedef void (*perf_irq_t)(struct pt_regs *); +extern perf_irq_t perf_irq; int reserve_pmc_hardware(perf_irq_t new_perf_irq); void release_pmc_hardware(void); -- cgit v1.2.3 From 4448aaf0faafff3f275d15937c28b6346760e028 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:34:42 -0800 Subject: [PATCH] s390: "extern inline" -> "static inline" "extern inline" -> "static inline" Signed-off-by: Adrian Bunk Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/s390/Debugging390.txt | 2 +- arch/s390/kernel/debug.c | 12 +++---- arch/s390/mm/fault.c | 2 +- drivers/s390/char/keyboard.h | 4 +-- drivers/s390/cio/qdio.h | 8 ++--- drivers/s390/net/fsm.h | 6 ++-- drivers/s390/s390mach.h | 2 +- include/asm-s390/debug.h | 16 ++++----- include/asm-s390/ebcdic.h | 2 +- include/asm-s390/io.h | 8 ++--- include/asm-s390/lowcore.h | 2 +- include/asm-s390/mmu_context.h | 2 +- include/asm-s390/pgtable.h | 68 ++++++++++++++++++------------------- include/asm-s390/sigp.h | 6 ++-- include/asm-s390/smp.h | 2 +- 15 files changed, 71 insertions(+), 71 deletions(-) (limited to 'include') diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt index adbfe620c061..844c03fe7921 100644 --- a/Documentation/s390/Debugging390.txt +++ b/Documentation/s390/Debugging390.txt @@ -871,7 +871,7 @@ by playing with the --adjust-vma parameter to objdump. -extern inline void spin_lock(spinlock_t *lp) +static inline void spin_lock(spinlock_t *lp) { a0: 18 34 lr %r3,%r4 a2: a7 3a 03 bc ahi %r3,956 diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index bc59282da762..896d39d0e4ce 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -486,7 +486,7 @@ out: * - goto next entry in p_info */ -extern inline int +static inline int debug_next_entry(file_private_info_t *p_info) { debug_info_t *id; @@ -800,7 +800,7 @@ debug_set_level(debug_info_t* id, int new_level) * - set active entry to next in the ring buffer */ -extern inline void +static inline void proceed_active_entry(debug_info_t * id) { if ((id->active_entries[id->active_area] += id->entry_size) @@ -817,7 +817,7 @@ proceed_active_entry(debug_info_t * id) * - set active area to next in the ring buffer */ -extern inline void +static inline void proceed_active_area(debug_info_t * id) { id->active_area++; @@ -828,7 +828,7 @@ proceed_active_area(debug_info_t * id) * get_active_entry: */ -extern inline debug_entry_t* +static inline debug_entry_t* get_active_entry(debug_info_t * id) { return (debug_entry_t *) (((char *) id->areas[id->active_area] @@ -841,7 +841,7 @@ get_active_entry(debug_info_t * id) * - set timestamp, caller address, cpu number etc. */ -extern inline void +static inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level, int exception) { @@ -971,7 +971,7 @@ debug_entry_t * counts arguments in format string for sprintf view */ -extern inline int +static inline int debug_count_numargs(char *string) { int numargs=0; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 64e32da77754..fb2607c369ed 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -160,7 +160,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, * 11 Page translation -> Not present (nullification) * 3b Region third trans. -> Not present (nullification) */ -extern inline void +static inline void do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) { struct task_struct *tsk; diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h index 3b4da5a9cf79..f7bf45c6bf0d 100644 --- a/drivers/s390/char/keyboard.h +++ b/drivers/s390/char/keyboard.h @@ -41,14 +41,14 @@ int kbd_ioctl(struct kbd_data *, struct file *, unsigned int, unsigned long); /* * Helper Functions. */ -extern inline void +static inline void kbd_put_queue(struct tty_struct *tty, int ch) { tty_insert_flip_char(tty, ch, 0); tty_schedule_flip(tty); } -extern inline void +static inline void kbd_puts_queue(struct tty_struct *tty, char *cp) { while (*cp) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 6b8aa6a852be..328e31cc6854 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -265,7 +265,7 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ /* * Some instructions as assembly */ -extern __inline__ int +static inline int do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) { int cc; @@ -300,7 +300,7 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) return cc; } -extern __inline__ int +static inline int do_siga_input(unsigned int irq, unsigned int mask) { int cc; @@ -334,7 +334,7 @@ do_siga_input(unsigned int irq, unsigned int mask) return cc; } -extern __inline__ int +static inline int do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) { int cc; @@ -401,7 +401,7 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) return cc; } -extern __inline__ unsigned long +static inline unsigned long do_clear_global_summary(void) { diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h index 1b8a7e7c34f3..5b98253be7aa 100644 --- a/drivers/s390/net/fsm.h +++ b/drivers/s390/net/fsm.h @@ -140,7 +140,7 @@ fsm_record_history(fsm_instance *fi, int state, int event); * 1 if current state or event is out of range * !0 if state and event in range, but no action defined. */ -extern __inline__ int +static inline int fsm_event(fsm_instance *fi, int event, void *arg) { fsm_function_t r; @@ -188,7 +188,7 @@ fsm_event(fsm_instance *fi, int event, void *arg) * @param fi Pointer to FSM * @param state The new state for this FSM. */ -extern __inline__ void +static inline void fsm_newstate(fsm_instance *fi, int newstate) { atomic_set(&fi->state,newstate); @@ -208,7 +208,7 @@ fsm_newstate(fsm_instance *fi, int newstate) * * @return The current state of the FSM. */ -extern __inline__ int +static inline int fsm_getstate(fsm_instance *fi) { return atomic_read(&fi->state); diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index 4eaa70179182..d9ea7ed2e46e 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h @@ -88,7 +88,7 @@ struct crw { #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ -extern __inline__ int stcrw(struct crw *pcrw ) +static inline int stcrw(struct crw *pcrw ) { int ccode; diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h index 7127030ae162..23450ed4b571 100644 --- a/include/asm-s390/debug.h +++ b/include/asm-s390/debug.h @@ -129,7 +129,7 @@ void debug_set_level(debug_info_t* id, int new_level); void debug_stop_all(void); -extern inline debug_entry_t* +static inline debug_entry_t* debug_event(debug_info_t* id, int level, void* data, int length) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) @@ -137,7 +137,7 @@ debug_event(debug_info_t* id, int level, void* data, int length) return debug_event_common(id,level,data,length); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_int_event(debug_info_t* id, int level, unsigned int tag) { unsigned int t=tag; @@ -146,7 +146,7 @@ debug_int_event(debug_info_t* id, int level, unsigned int tag) return debug_event_common(id,level,&t,sizeof(unsigned int)); } -extern inline debug_entry_t * +static inline debug_entry_t * debug_long_event (debug_info_t* id, int level, unsigned long tag) { unsigned long t=tag; @@ -155,7 +155,7 @@ debug_long_event (debug_info_t* id, int level, unsigned long tag) return debug_event_common(id,level,&t,sizeof(unsigned long)); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_text_event(debug_info_t* id, int level, const char* txt) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) @@ -168,7 +168,7 @@ debug_sprintf_event(debug_info_t* id,int level,char *string,...) __attribute__ ((format(printf, 3, 4))); -extern inline debug_entry_t* +static inline debug_entry_t* debug_exception(debug_info_t* id, int level, void* data, int length) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) @@ -176,7 +176,7 @@ debug_exception(debug_info_t* id, int level, void* data, int length) return debug_exception_common(id,level,data,length); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_int_exception(debug_info_t* id, int level, unsigned int tag) { unsigned int t=tag; @@ -185,7 +185,7 @@ debug_int_exception(debug_info_t* id, int level, unsigned int tag) return debug_exception_common(id,level,&t,sizeof(unsigned int)); } -extern inline debug_entry_t * +static inline debug_entry_t * debug_long_exception (debug_info_t* id, int level, unsigned long tag) { unsigned long t=tag; @@ -194,7 +194,7 @@ debug_long_exception (debug_info_t* id, int level, unsigned long tag) return debug_exception_common(id,level,&t,sizeof(unsigned long)); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_text_exception(debug_info_t* id, int level, const char* txt) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h index 20e81e885821..4cbc336e4d60 100644 --- a/include/asm-s390/ebcdic.h +++ b/include/asm-s390/ebcdic.h @@ -21,7 +21,7 @@ extern __u8 _ebcasc[]; /* EBCDIC -> ASCII conversion table */ extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */ extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */ -extern __inline__ void +static inline void codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr) { if (nr-- <= 0) diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h index 8188fdc9884f..71f55eb2350a 100644 --- a/include/asm-s390/io.h +++ b/include/asm-s390/io.h @@ -24,7 +24,7 @@ * Change virtual addresses to physical addresses and vv. * These are pretty trivial */ -extern inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile void * address) { unsigned long real_address; __asm__ ( @@ -42,7 +42,7 @@ extern inline unsigned long virt_to_phys(volatile void * address) return real_address; } -extern inline void * phys_to_virt(unsigned long address) +static inline void * phys_to_virt(unsigned long address) { return __io_virt(address); } @@ -54,7 +54,7 @@ extern inline void * phys_to_virt(unsigned long address) extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); -extern inline void * ioremap (unsigned long offset, unsigned long size) +static inline void * ioremap (unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } @@ -64,7 +64,7 @@ extern inline void * ioremap (unsigned long offset, unsigned long size) * it's useful if some control registers are in such an area and write combining * or read caching is not desirable: */ -extern inline void * ioremap_nocache (unsigned long offset, unsigned long size) +static inline void * ioremap_nocache (unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index c6f51c9ce3ff..db0606c1abd4 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h @@ -346,7 +346,7 @@ struct _lowcore #define S390_lowcore (*((struct _lowcore *) 0)) extern struct _lowcore *lowcore_ptr[]; -extern __inline__ void set_prefix(__u32 address) +static inline void set_prefix(__u32 address) { __asm__ __volatile__ ("spx %0" : : "m" (address) : "memory" ); } diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h index 3a3bb3f2dad5..bcf24a873874 100644 --- a/include/asm-s390/mmu_context.h +++ b/include/asm-s390/mmu_context.h @@ -44,7 +44,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, #define deactivate_mm(tsk,mm) do { } while (0) -extern inline void activate_mm(struct mm_struct *prev, +static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { switch_mm(prev, next, current); diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 9be741bb1496..859b5e969826 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -319,7 +319,7 @@ extern char empty_zero_page[PAGE_SIZE]; * within a page table are directly modified. Thus, the following * hook is made available. */ -extern inline void set_pte(pte_t *pteptr, pte_t pteval) +static inline void set_pte(pte_t *pteptr, pte_t pteval) { *pteptr = pteval; } @@ -330,63 +330,63 @@ extern inline void set_pte(pte_t *pteptr, pte_t pteval) */ #ifndef __s390x__ -extern inline int pgd_present(pgd_t pgd) { return 1; } -extern inline int pgd_none(pgd_t pgd) { return 0; } -extern inline int pgd_bad(pgd_t pgd) { return 0; } +static inline int pgd_present(pgd_t pgd) { return 1; } +static inline int pgd_none(pgd_t pgd) { return 0; } +static inline int pgd_bad(pgd_t pgd) { return 0; } -extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; } -extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } -extern inline int pmd_bad(pmd_t pmd) +static inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; } +static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } +static inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE; } #else /* __s390x__ */ -extern inline int pgd_present(pgd_t pgd) +static inline int pgd_present(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY; } -extern inline int pgd_none(pgd_t pgd) +static inline int pgd_none(pgd_t pgd) { return pgd_val(pgd) & _PGD_ENTRY_INV; } -extern inline int pgd_bad(pgd_t pgd) +static inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY; } -extern inline int pmd_present(pmd_t pmd) +static inline int pmd_present(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY; } -extern inline int pmd_none(pmd_t pmd) +static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PMD_ENTRY_INV; } -extern inline int pmd_bad(pmd_t pmd) +static inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY; } #endif /* __s390x__ */ -extern inline int pte_none(pte_t pte) +static inline int pte_none(pte_t pte) { return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_EMPTY; } -extern inline int pte_present(pte_t pte) +static inline int pte_present(pte_t pte) { return !(pte_val(pte) & _PAGE_INVALID) || (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_NONE; } -extern inline int pte_file(pte_t pte) +static inline int pte_file(pte_t pte) { return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_FILE; } @@ -397,12 +397,12 @@ extern inline int pte_file(pte_t pte) * query functions pte_write/pte_dirty/pte_young only work if * pte_present() is true. Undefined behaviour if not.. */ -extern inline int pte_write(pte_t pte) +static inline int pte_write(pte_t pte) { return (pte_val(pte) & _PAGE_RO) == 0; } -extern inline int pte_dirty(pte_t pte) +static inline int pte_dirty(pte_t pte) { /* A pte is neither clean nor dirty on s/390. The dirty bit * is in the storage key. See page_test_and_clear_dirty for @@ -411,7 +411,7 @@ extern inline int pte_dirty(pte_t pte) return 0; } -extern inline int pte_young(pte_t pte) +static inline int pte_young(pte_t pte) { /* A pte is neither young nor old on s/390. The young bit * is in the storage key. See page_test_and_clear_young for @@ -420,7 +420,7 @@ extern inline int pte_young(pte_t pte) return 0; } -extern inline int pte_read(pte_t pte) +static inline int pte_read(pte_t pte) { /* All pages are readable since we don't use the fetch * protection bit in the storage key. @@ -434,9 +434,9 @@ extern inline int pte_read(pte_t pte) #ifndef __s390x__ -extern inline void pgd_clear(pgd_t * pgdp) { } +static inline void pgd_clear(pgd_t * pgdp) { } -extern inline void pmd_clear(pmd_t * pmdp) +static inline void pmd_clear(pmd_t * pmdp) { pmd_val(pmdp[0]) = _PAGE_TABLE_INV; pmd_val(pmdp[1]) = _PAGE_TABLE_INV; @@ -446,12 +446,12 @@ extern inline void pmd_clear(pmd_t * pmdp) #else /* __s390x__ */ -extern inline void pgd_clear(pgd_t * pgdp) +static inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; } -extern inline void pmd_clear(pmd_t * pmdp) +static inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; @@ -459,7 +459,7 @@ extern inline void pmd_clear(pmd_t * pmdp) #endif /* __s390x__ */ -extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_val(*ptep) = _PAGE_INVALID_EMPTY; } @@ -468,14 +468,14 @@ extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt * The following pte modification functions only work if * pte_present() is true. Undefined behaviour if not.. */ -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) &= PAGE_MASK; pte_val(pte) |= pgprot_val(newprot); return pte; } -extern inline pte_t pte_wrprotect(pte_t pte) +static inline pte_t pte_wrprotect(pte_t pte) { /* Do not clobber _PAGE_INVALID_NONE pages! */ if (!(pte_val(pte) & _PAGE_INVALID)) @@ -483,13 +483,13 @@ extern inline pte_t pte_wrprotect(pte_t pte) return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) +static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_RO; return pte; } -extern inline pte_t pte_mkclean(pte_t pte) +static inline pte_t pte_mkclean(pte_t pte) { /* The only user of pte_mkclean is the fork() code. We must *not* clear the *physical* page dirty bit @@ -498,7 +498,7 @@ extern inline pte_t pte_mkclean(pte_t pte) return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) +static inline pte_t pte_mkdirty(pte_t pte) { /* We do not explicitly set the dirty bit because the * sske instruction is slow. It is faster to let the @@ -507,7 +507,7 @@ extern inline pte_t pte_mkdirty(pte_t pte) return pte; } -extern inline pte_t pte_mkold(pte_t pte) +static inline pte_t pte_mkold(pte_t pte) { /* S/390 doesn't keep its dirty/referenced bit in the pte. * There is no point in clearing the real referenced bit. @@ -515,7 +515,7 @@ extern inline pte_t pte_mkold(pte_t pte) return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) +static inline pte_t pte_mkyoung(pte_t pte) { /* S/390 doesn't keep its dirty/referenced bit in the pte. * There is no point in setting the real referenced bit. @@ -695,7 +695,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) #ifndef __s390x__ /* Find an entry in the second-level page table.. */ -extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) { return (pmd_t *) dir; } @@ -758,7 +758,7 @@ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) #else #define __SWP_OFFSET_MASK (~0UL >> 11) #endif -extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) +static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; offset &= __SWP_OFFSET_MASK; diff --git a/include/asm-s390/sigp.h b/include/asm-s390/sigp.h index 3979bc3858e2..fc56458aff66 100644 --- a/include/asm-s390/sigp.h +++ b/include/asm-s390/sigp.h @@ -67,7 +67,7 @@ typedef enum /* * Signal processor */ -extern __inline__ sigp_ccode +static inline sigp_ccode signal_processor(__u16 cpu_addr, sigp_order_code order_code) { sigp_ccode ccode; @@ -86,7 +86,7 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code) /* * Signal processor with parameter */ -extern __inline__ sigp_ccode +static inline sigp_ccode signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code) { @@ -107,7 +107,7 @@ signal_processor_p(__u32 parameter, __u16 cpu_addr, /* * Signal processor with parameter and return status */ -extern __inline__ sigp_ccode +static inline sigp_ccode signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr, sigp_order_code order_code) { diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h index dd50e57a928f..a2ae7628bbaa 100644 --- a/include/asm-s390/smp.h +++ b/include/asm-s390/smp.h @@ -52,7 +52,7 @@ extern int smp_call_function_on(void (*func) (void *info), void *info, extern int smp_get_cpu(cpumask_t cpu_map); extern void smp_put_cpu(int cpu); -extern __inline__ __u16 hard_smp_processor_id(void) +static inline __u16 hard_smp_processor_id(void) { __u16 cpu_address; -- cgit v1.2.3 From 733482e445ca4450cf41381b1c95e2b8c7145114 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 8 Nov 2005 21:34:55 -0800 Subject: [PATCH] changing CONFIG_LOCALVERSION rebuilds too much, for no good reason This patch removes almost all inclusions of linux/version.h. The 3 #defines are unused in most of the touched files. A few drivers use the simple KERNEL_VERSION(a,b,c) macro, which is unfortunatly in linux/version.h. There are also lots of #ifdef for long obsolete kernels, this was not touched. In a few places, the linux/version.h include was move to where the LINUX_VERSION_CODE was used. quilt vi `find * -type f -name "*.[ch]"|xargs grep -El '(UTS_RELEASE|LINUX_VERSION_CODE|KERNEL_VERSION|linux/version.h)'|grep -Ev '(/(boot|coda|drm)/|~$)'` search pattern: /UTS_RELEASE\|LINUX_VERSION_CODE\|KERNEL_VERSION\|linux\/\(utsname\|version\).h Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-omap1/leds-h2p2-debug.c | 1 - arch/arm/plat-omap/ocpi.c | 1 - arch/cris/arch-v10/drivers/pcf8563.c | 1 - arch/cris/arch-v10/kernel/fasttimer.c | 1 - arch/cris/arch-v32/drivers/nandflash.c | 1 - arch/cris/arch-v32/drivers/pcf8563.c | 1 - arch/mips/tx4938/toshiba_rbtx4938/irq.c | 1 - arch/parisc/kernel/asm-offsets.c | 1 - arch/ppc/syslib/prom.c | 1 - arch/ppc/syslib/prom_init.c | 1 - drivers/block/amiflop.c | 1 - drivers/char/ip2.c | 1 - drivers/char/mwave/tp3780i.c | 1 - drivers/char/mxser.c | 1 - drivers/char/specialix.c | 1 - drivers/char/tpm/tpm.h | 1 - drivers/char/viocons.c | 1 - drivers/char/viotape.c | 1 - drivers/firmware/dell_rbu.c | 1 - drivers/infiniband/ulp/srp/ib_srp.c | 1 - drivers/isdn/divert/divert_init.c | 1 - drivers/isdn/divert/divert_procfs.c | 1 - drivers/isdn/divert/isdn_divert.c | 1 - drivers/isdn/hisax/hisax_fcpcipnp.c | 1 - drivers/isdn/hisax/st5481_init.c | 1 - drivers/isdn/hysdn/hycapi.c | 1 - drivers/isdn/hysdn/hysdn_init.c | 1 - drivers/isdn/hysdn/hysdn_net.c | 1 - drivers/isdn/hysdn/hysdn_procconf.c | 1 - drivers/isdn/hysdn/hysdn_proclog.c | 1 - drivers/isdn/i4l/isdn_common.c | 1 - drivers/isdn/icn/icn.h | 1 - drivers/isdn/isdnloop/isdnloop.h | 1 - drivers/isdn/sc/includes.h | 1 - drivers/md/bitmap.c | 1 - drivers/media/video/arv.c | 1 - drivers/media/video/zr36016.c | 1 - drivers/media/video/zr36050.c | 1 - drivers/media/video/zr36060.c | 1 - drivers/message/fusion/mptbase.c | 1 - drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptctl.c | 1 - drivers/message/fusion/mptctl.h | 1 - drivers/message/fusion/mptlan.h | 1 - drivers/misc/hdpuftrs/hdpu_cpustate.c | 1 - drivers/misc/hdpuftrs/hdpu_nexus.c | 1 - drivers/misc/ibmasm/ibmasm.h | 1 - drivers/mtd/chips/cfi_cmdset_0020.c | 1 - drivers/mtd/devices/pmc551.c | 1 - drivers/mtd/maps/ebony.c | 1 - drivers/mtd/maps/ocotea.c | 1 - drivers/mtd/maps/walnut.c | 1 - drivers/mtd/nand/au1550nd.c | 1 + drivers/mtd/nand/autcpu12.c | 1 - drivers/net/b44.c | 1 - drivers/net/cassini.c | 1 - drivers/net/dm9000.c | 1 - drivers/net/fs_enet/fs_enet.h | 1 - drivers/net/gianfar.c | 1 - drivers/net/gianfar.h | 1 - drivers/net/gianfar_ethtool.c | 1 - drivers/net/gianfar_mii.c | 1 - drivers/net/hp100.c | 1 - drivers/net/ibmveth.c | 1 - drivers/net/iseries_veth.c | 1 - drivers/net/mac8390.c | 1 - drivers/net/mv643xx_eth.h | 1 - drivers/net/s2io.c | 1 - drivers/net/sk98lin/h/skdrv1st.h | 3 --- drivers/net/sk_mca.c | 1 - drivers/net/sk_mca.h | 2 -- drivers/net/starfire.c | 1 - drivers/net/via-velocity.c | 1 - drivers/net/wireless/hostap/hostap.c | 1 - drivers/net/wireless/hostap/hostap_hw.c | 1 - drivers/net/wireless/hostap/hostap_pci.c | 1 - drivers/net/wireless/hostap/hostap_plx.c | 1 - drivers/net/wireless/ipw2100.h | 1 - drivers/net/wireless/ipw2200.c | 1 + drivers/net/wireless/ipw2200.h | 1 - drivers/net/wireless/orinoco.h | 1 - drivers/net/wireless/prism54/isl_38xx.c | 1 - drivers/net/wireless/prism54/isl_38xx.h | 1 - drivers/net/wireless/prism54/isl_ioctl.c | 1 - drivers/net/wireless/prism54/islpci_dev.c | 1 - drivers/net/wireless/prism54/islpci_dev.h | 1 - drivers/net/wireless/prism54/islpci_eth.c | 1 - drivers/net/wireless/prism54/islpci_hotplug.c | 1 - drivers/pcmcia/au1000_pb1x00.c | 1 - drivers/pcmcia/au1000_xxs1500.c | 1 - drivers/s390/crypto/z90main.c | 1 - drivers/s390/net/claw.c | 1 - drivers/scsi/3w-xxxx.h | 1 - drivers/scsi/a2091.c | 1 - drivers/scsi/aic7xxx/aic79xx_osm.h | 1 - drivers/scsi/aic7xxx/aic7xxx_osm.h | 1 - drivers/scsi/amiga7xx.c | 1 - drivers/scsi/bvme6000.c | 1 - drivers/scsi/gvp11.c | 1 - drivers/scsi/ibmmca.c | 6 ------ drivers/scsi/ips.h | 1 + drivers/scsi/megaraid/mega_common.h | 1 - drivers/scsi/megaraid/megaraid_mm.h | 1 - drivers/scsi/megaraid/megaraid_sas.c | 1 - drivers/scsi/mvme147.c | 1 - drivers/scsi/mvme16x.c | 1 - drivers/scsi/nsp32.h | 1 + drivers/scsi/pci2000.h | 3 --- drivers/scsi/scsi_debug.c | 4 ---- drivers/scsi/sg.c | 4 ---- drivers/scsi/sgiwd93.c | 1 - drivers/scsi/wd33c93.c | 1 - drivers/telephony/ixj.h | 1 - drivers/usb/gadget/dummy_hcd.c | 1 - drivers/usb/gadget/lh7a40x_udc.h | 1 - drivers/usb/gadget/pxa2xx_udc.c | 1 - drivers/usb/gadget/rndis.c | 1 - drivers/usb/host/hc_crisv10.c | 1 - drivers/usb/media/pwc/pwc-if.c | 1 + drivers/usb/media/pwc/pwc.h | 2 -- drivers/usb/media/w9968cf.c | 1 - drivers/usb/misc/sisusbvga/sisusb.c | 1 - drivers/usb/misc/sisusbvga/sisusb.h | 1 + drivers/usb/misc/sisusbvga/sisusb_con.c | 1 - drivers/usb/misc/sisusbvga/sisusb_init.c | 1 - drivers/video/backlight/backlight.c | 1 - drivers/video/backlight/lcd.c | 1 - drivers/video/intelfb/intelfbdrv.c | 1 - drivers/video/intelfb/intelfbhw.c | 1 - fs/9p/vfs_file.c | 1 - fs/adfs/adfs.h | 1 - fs/hfs/hfs_fs.h | 1 - fs/hfs/inode.c | 1 - fs/hfsplus/bnode.c | 1 - fs/hfsplus/dir.c | 1 - fs/hfsplus/extents.c | 1 - fs/hfsplus/hfsplus_fs.h | 1 - fs/hfsplus/inode.c | 1 - fs/hfsplus/super.c | 1 - fs/hfsplus/wrapper.c | 1 - fs/hostfs/hostfs_kern.c | 1 - fs/xfs/linux-2.6/xfs_linux.h | 1 - fs/xfs/xfs.h | 7 ------- fs/xfs/xfs_dmapi.h | 1 + include/linux/fs_enet_pd.h | 1 - include/linux/if_wanpipe_common.h | 2 -- include/linux/istallion.h | 2 -- include/linux/mtd/cfi.h | 1 - include/linux/mtd/mtd.h | 1 - include/linux/phonedev.h | 1 - include/linux/stallion.h | 2 -- sound/oss/msnd.c | 1 - sound/oss/os.h | 2 -- sound/oss/rme96xx.c | 1 - sound/oss/sh_dac_audio.c | 1 - sound/ppc/pmac.h | 1 - 156 files changed, 7 insertions(+), 176 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c index be283cda63dd..399010c14036 100644 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index 1fb16f9edfd5..2ede2ee8cae4 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index 201f4c90d961..f2c55742e90c 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c @@ -19,7 +19,6 @@ */ #include -#include #include #include #include diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 094ff45ae85b..cac05a5e514c 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c @@ -112,7 +112,6 @@ #include #include -#include #include #include diff --git a/arch/cris/arch-v32/drivers/nandflash.c b/arch/cris/arch-v32/drivers/nandflash.c index fc2a619b035d..93ddea4d9564 100644 --- a/arch/cris/arch-v32/drivers/nandflash.c +++ b/arch/cris/arch-v32/drivers/nandflash.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c index f894580b648b..d788bda3578c 100644 --- a/arch/cris/arch-v32/drivers/pcf8563.c +++ b/arch/cris/arch-v32/drivers/pcf8563.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 230f5a93c2e6..9cd9c0fe2265 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -84,7 +84,6 @@ IRQ Device #include #include #include -#include #include #include diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index 1ad44f92d6e4..e23c4e1e3a25 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 03b1fc9b9501..af4deace49e0 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index 7f15136830f4..df14422ae1c6 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 1468e8cf712d..0acbfff8ad28 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1816,7 +1816,6 @@ out_blkdev: } #ifdef MODULE -#include int init_module(void) { diff --git a/drivers/char/ip2.c b/drivers/char/ip2.c index 6cd12f23aa58..7cadfc6ef352 100644 --- a/drivers/char/ip2.c +++ b/drivers/char/ip2.c @@ -7,7 +7,6 @@ // #include -#include #include #include diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index d6c72e0934e2..cc3e54dd7234 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c @@ -46,7 +46,6 @@ * First release to the public */ -#include #include #include #include diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3b965a651da4..26448f176803 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 352547eabf7b..0bbfce43031c 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -90,7 +90,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 99a60496ecc6..9293bcc4dc62 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -19,7 +19,6 @@ * */ #include -#include #include #include #include diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 98601c7d04a9..4d75c261f98a 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -26,7 +26,6 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 867cc4e418c7..60aabdb4a046 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -32,7 +32,6 @@ * iseries/vio.h */ #include -#include #include #include #include diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index ba17292eb290..6d83299e7c9b 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -34,7 +34,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include #include #include #include diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 2687e34aa5bc..321a3a10e69b 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -32,7 +32,6 @@ * $Id: ib_srp.c 3932 2005-11-01 17:19:29Z roland $ */ -#include #include #include #include diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c index 434e684f5dbb..2f7c9fc2e898 100644 --- a/drivers/isdn/divert/divert_init.c +++ b/drivers/isdn/divert/divert_init.c @@ -10,7 +10,6 @@ */ #include -#include #include #include diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 0b0ea26023e5..1b37d86d5ee1 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 0bfd698726a6..f1a1f9a9b88e 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -9,7 +9,6 @@ * */ -#include #include #include "isdn_divert.h" diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index b4d795d40154..dc7ef957e897 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -23,7 +23,6 @@ * o tx_skb at PH_DEACTIVATE time */ -#include #include #include #include diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 2cf5d1a6df6c..8e192a3a3490 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -25,7 +25,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 1fd3d4e5f284..acc1d3cceebb 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c index 12c8137b5161..cb791f8e793a 100644 --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index babec8157ae6..aa01628d74c6 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 87f59a0e2a95..40e56143c768 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 4d57011c5737..6c26f1efabd5 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8a7d54a5c97d..4643df097bfe 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 9028cc3b5071..7d7245fb0b32 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -35,7 +35,6 @@ typedef struct icn_cdef { #ifdef __KERNEL__ /* Kernel includes */ -#include #include #include #include diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index 8fb7bc1bfe0f..d699fe53e1c3 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -33,7 +33,6 @@ typedef struct isdnloop_sdef { #ifdef __KERNEL__ /* Kernel includes */ -#include #include #include #include diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h index 4611da6e9231..5286e0c810a9 100644 --- a/drivers/isdn/sc/includes.h +++ b/drivers/isdn/sc/includes.h @@ -4,7 +4,6 @@ * */ -#include #include #include #include diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 01654fcabc52..e59694bc5758 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 0823ddaf7004..881cdcb1875d 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index d4740a89cea1..4ed898585c70 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -26,7 +26,6 @@ #define ZR016_VERSION "v0.7" -#include #include #include #include diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index 13b1e7b6fd6e..0144576a6123 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -26,7 +26,6 @@ #define ZR050_VERSION "v0.7.1" -#include #include #include #include diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index b50dc403e6db..129744a07abd 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -26,7 +26,6 @@ #define ZR060_VERSION "v0.7" -#include #include #include #include diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 790a2932ded9..65c2ec5c421b 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -47,7 +47,6 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #include -#include #include #include #include diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e7efeb7740b9..5f5b3fb5b4d7 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -49,7 +49,6 @@ #define MPTBASE_H_INCLUDED /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include #include #include #include diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index cb2d59d5f5af..602138f8544d 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -45,7 +45,6 @@ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include #include #include #include diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index 28754a9cb803..518996e03481 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -49,7 +49,6 @@ #define MPTCTL_H_INCLUDED /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include "linux/version.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 750e343eb981..3726ecba5707 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -66,7 +66,6 @@ #include #include #include -#include #include #include // #include diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c index 9c4dd682ac74..bc2b72b32905 100644 --- a/drivers/misc/hdpuftrs/hdpu_cpustate.c +++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c index 165f3405df27..4bb461793851 100644 --- a/drivers/misc/hdpuftrs/hdpu_nexus.c +++ b/drivers/misc/hdpuftrs/hdpu_nexus.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index ecce4ffd3e23..d7e20a34f88d 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index c4a19d2dc67f..0807c1c91e55 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -20,7 +20,6 @@ * - Plugged memory leak in cfi_staa_writev(). */ -#include #include #include #include diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index de48b35f5609..666cce1bf60c 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -82,7 +82,6 @@ * * Comb the init routine. It's still a bit cludgy on a few things. */ -#include #include #include #include diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c index c0daf58357ca..60a6e51d662f 100644 --- a/drivers/mtd/maps/ebony.c +++ b/drivers/mtd/maps/ebony.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c index 6e559bc14636..c223514ca2eb 100644 --- a/drivers/mtd/maps/ocotea.c +++ b/drivers/mtd/maps/ocotea.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c index 5c17bca3a37e..f46bec66150f 100644 --- a/drivers/mtd/maps/walnut.c +++ b/drivers/mtd/maps/walnut.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 3cafcdf28aed..9c5945d6df88 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* fixme: this is ugly */ diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 056dfc17a075..a3c7fea404d0 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -27,7 +27,6 @@ * 10-06-2002 TG 128K card support added */ -#include #include #include #include diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 0ee3e27969c6..819a17921cb9 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 50f43dbf31ae..1f7ca453bb4a 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -67,7 +67,6 @@ */ #include -#include #include #include diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index c0af6fb1fbba..f8c9bcdab68b 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 1105543b9d88..e7ec96c964a9 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 962580f2c4ab..54d294ad6df5 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -90,7 +90,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index c77ca6c0d04a..220084e53341 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 68e3578e7613..5a2d810ce575 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 5a74d3d3dbe1..7263395d78bb 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index b71fab6e34f4..e92c17f6931c 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -96,7 +96,6 @@ #undef HP100_MULTICAST_FILTER /* Need to be debugged... */ -#include #include #include #include diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 94239f67f3a3..be191d80ef9c 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index d86d8f055a6c..77eadf84cb2c 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -58,7 +58,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index ce5761816a64..d8c99f038fa0 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -15,7 +15,6 @@ * and fixed access to Sonic Sys card which masquerades as a Farallon * by rayk@knightsmanor.org */ -#include #include #include #include diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index bcfda5192da0..f769f9b626ea 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -1,7 +1,6 @@ #ifndef __MV643XX_ETH_H__ #define __MV643XX_ETH_H__ -#include #include #include #include diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 0745dd9d01f3..8e41f4cea272 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h index 308440bd0e12..91b8d4f45904 100644 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ b/drivers/net/sk98lin/h/skdrv1st.h @@ -39,9 +39,6 @@ #ifndef __INC_SKDRV1ST_H #define __INC_SKDRV1ST_H -/* Check kernel version */ -#include - typedef struct s_AC SK_AC; /* Set card versions */ diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c index 4c56b8d8221b..e5d6d95960c7 100644 --- a/drivers/net/sk_mca.c +++ b/drivers/net/sk_mca.c @@ -93,7 +93,6 @@ History: #include #include #include -#include #include #include #include diff --git a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h index 7e7c99582746..d6fa1823dfa6 100644 --- a/drivers/net/sk_mca.h +++ b/drivers/net/sk_mca.h @@ -1,5 +1,3 @@ -#include - #ifndef _SK_MCA_INCLUDE_ #define _SK_MCA_INCLUDE_ diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 38b2b0a3ce96..d167deda9a53 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -147,7 +147,6 @@ TODO: - fix forced speed/duplexing code (broken a long time ago, when #define DRV_RELDATE "October 3, 2005" #include -#include #include #include #include diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index a368d08e7d19..82c6b757d306 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c index 6a96cd9f2685..3d2ea61033be 100644 --- a/drivers/net/wireless/hostap/hostap.c +++ b/drivers/net/wireless/hostap/hostap.c @@ -13,7 +13,6 @@ */ #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 59fc15572395..abfae7fedebc 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -31,7 +31,6 @@ #include -#include #include #include diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index da0c80fb941c..2e85bdced2dd 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -5,7 +5,6 @@ * Andy Warner */ #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 78d67b408b2f..94fe2449f099 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -8,7 +8,6 @@ #include -#include #include #include #include diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index c9e99ce15d66..1f23650c077f 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -37,7 +37,6 @@ #include #include #include -#include #include // new driver API #include diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3db0c32afe82..589aef8ba4e6 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -31,6 +31,7 @@ ******************************************************************************/ #include "ipw2200.h" +#include #define IPW2200_VERSION "1.0.0" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e9cf32bf3e31..0873b758f499 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 7a17bb31fc89..f5d856db92a1 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "hermes.h" diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index adc7499136dc..aaa958798f3f 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h index e83e4912ab66..8af20980af8d 100644 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ b/drivers/net/wireless/prism54/isl_38xx.h @@ -20,7 +20,6 @@ #ifndef _ISL_38XX_H #define _ISL_38XX_H -#include #include #include diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 5c1a1adf1ff8..135a156db25d 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -20,7 +20,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 78bdb359835e..5ddf29599032 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -19,7 +19,6 @@ * */ -#include #include #include diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index efbed4397951..07053165e4c5 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -23,7 +23,6 @@ #ifndef _ISLPCI_DEV_H #define _ISLPCI_DEV_H -#include #include #include #include diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index fc1eb3564832..80ae081ab4b7 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -17,7 +17,6 @@ * */ -#include #include #include diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index dc040caab7d7..b41d666fea3c 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index d414a3bb50b9..86c0808d6a05 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c index f113b69d699b..01a895bc9a47 100644 --- a/drivers/pcmcia/au1000_xxs1500.c +++ b/drivers/pcmcia/au1000_xxs1500.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 04c2ef778ec6..4010f2bb85af 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "z90crypt.h" #include "z90common.h" diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 1a1c3decea72..6b63d21612ec 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -88,7 +88,6 @@ #include #include #include -#include #include "cu3088.h" #include "claw.h" diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 98bad773f240..4f81fc39ec57 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -54,7 +54,6 @@ #ifndef _3W_XXXX_H #define _3W_XXXX_H -#include #include /* AEN strings */ diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index f7a1751e892d..30a14ba77a6a 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 052c6619accc..bc44222d6cc3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index be9edbe26dbe..f2a95447142c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -66,7 +66,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c index 5f13546d6392..dea8446f5360 100644 --- a/drivers/scsi/amiga7xx.c +++ b/drivers/scsi/amiga7xx.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c index 29c7ed30c09e..130f30f51a9b 100644 --- a/drivers/scsi/bvme6000.c +++ b/drivers/scsi/bvme6000.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index d12342fa8199..ab22387c9df1 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 887a5c3ded28..8d97999db60e 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -18,12 +18,6 @@ */ #include -#ifndef LINUX_VERSION_CODE -#include -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) -#error "This driver works only with kernel 2.5.45 or higher!" -#endif #include #include #include diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 505e967013de..adc6eabbf610 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -50,6 +50,7 @@ #ifndef _IPS_H_ #define _IPS_H_ +#include #include #include diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 69df1a9b935d..8e547130e97d 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h index 7e36c46e7c43..eb8c390a0fa3 100644 --- a/drivers/scsi/megaraid/megaraid_mm.h +++ b/drivers/scsi/megaraid/megaraid_mm.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 4245d05e628b..801a63bea8a5 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 2fb31ee6d9f5..33380cee9b77 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c index b2d8d8ea1604..29ec699e0e4d 100644 --- a/drivers/scsi/mvme16x.c +++ b/drivers/scsi/mvme16x.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index 5664398fa0ad..5addf9fb1e15 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -16,6 +16,7 @@ #ifndef _NSP32_H #define _NSP32_H +#include //#define NSP32_DEBUG 9 /* diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h index c65afc964121..6c962d7dca47 100644 --- a/drivers/scsi/pci2000.h +++ b/drivers/scsi/pci2000.h @@ -26,9 +26,6 @@ #ifndef PSI_EIDE_SCSIOP #define PSI_EIDE_SCSIOP 1 -#ifndef LINUX_VERSION_CODE -#include -#endif #define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s)) /************************************************/ diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index aadf051274fa..b61fb1295b8b 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -48,10 +48,6 @@ #include -#ifndef LINUX_VERSION_CODE -#include -#endif - #include "scsi_logging.h" #include "scsi_debug.h" diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 62e3f340cc52..72ec59456e69 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -68,10 +68,6 @@ static int sg_proc_init(void); static void sg_proc_cleanup(void); #endif -#ifndef LINUX_VERSION_CODE -#include -#endif /* LINUX_VERSION_CODE */ - #define SG_ALLOW_DIO_DEF 0 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index 09fd203e4b86..f37147f8f7bf 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 5754445fb36a..fd63add6a577 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index 51e3f7f6597b..fbea4541c234 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -40,7 +40,6 @@ *****************************************************************************/ #define IXJ_VERSION 3031 -#include #include #include diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 975ace3f5b1e..904519085334 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h index 1bb455c045a9..9b2e6f7cbb8b 100644 --- a/drivers/usb/gadget/lh7a40x_udc.h +++ b/drivers/usb/gadget/lh7a40x_udc.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index ee9cd7869d92..510d28a924db 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 06b6eba925b5..9689efeb364c 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index a8267cf17db4..0eaabeb37ac3 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index b77e65c03659..5524fd70210b 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include "pwc.h" diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h index 267869dab185..6dd76bb3dff1 100644 --- a/drivers/usb/media/pwc/pwc.h +++ b/drivers/usb/media/pwc/pwc.h @@ -25,8 +25,6 @@ #ifndef PWC_H #define PWC_H -#include - #include #include #include diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index f36c0b6c6e36..67612c81cb9f 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -25,7 +25,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index c946c9a538a0..41ef2b606751 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -37,7 +37,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index 401ff21d7881..1d7a77cc7c4a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h @@ -37,6 +37,7 @@ #ifndef _SISUSB_H_ #define _SISUSB_H_ +#include #ifdef CONFIG_COMPAT #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) #include diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 24584463553d..be5c1a25ae21 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -48,7 +48,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index f28bc240f9b6..044fa4482f9f 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c @@ -37,7 +37,6 @@ */ #include -#include #include #include #include diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index acc81cb01d56..9d5015e99372 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -5,7 +5,6 @@ * */ -#include #include #include #include diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 470e6f0ee4dd..68c690605aa7 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -5,7 +5,6 @@ * */ -#include #include #include #include diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 0799b999b314..427689e584da 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -122,7 +122,6 @@ #include #include #include -#include #include diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index ac94c2e5ff85..624c4bc96f0d 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -34,7 +34,6 @@ #include #include #include -#include #include diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index bbc3cc63854f..89c849da8504 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index fd528433de43..f6cd01352cc8 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -12,7 +12,6 @@ #define ADFS_NDA_PUBLIC_READ (1 << 5) #define ADFS_NDA_PUBLIC_WRITE (1 << 6) -#include #include "dir_f.h" struct buffer_head; diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index aae019aadf88..cc5dcd52e23d 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -9,7 +9,6 @@ #ifndef _LINUX_HFS_FS_H #define _LINUX_HFS_FS_H -#include #include #include #include diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 3f680c5675bf..d499393a8ae7 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -12,7 +12,6 @@ */ #include -#include #include #include "hfs_fs.h" diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index b85abc6e6f83..930cd9212de8 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 7bda76667a4a..50c8f44b6c66 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index e7235ca79a95..e3ff56a03011 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 2bc0cdd30e56..c60e5635498d 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -11,7 +11,6 @@ #define _LINUX_HFSPLUS_FS_H #include -#include #include #include "hfsplus_raw.h" diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index f205773ddfbe..fc98583cf045 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "hfsplus_fs.h" diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 452fc1fdbd32..0ce1c455ae55 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 0c51d6338b0b..95455e839231 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "hfsplus_fs.h" diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index a33fb1d91373..4684eb7d48c6 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 44fed10af0dd..d8e21ba0cccc 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -72,7 +72,6 @@ #include #include #include -#include #include #include diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 99b50d2bda9b..1a48dbb902a7 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -17,12 +17,5 @@ */ #ifndef __XFS_H__ #define __XFS_H__ - -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include -#else -#include -#endif - #endif /* __XFS_H__ */ diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 5a5c7a63e80b..864bf6955689 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -18,6 +18,7 @@ #ifndef __XFS_DMAPI_H__ #define __XFS_DMAPI_H__ +#include /* Values used to define the on-disk version of dm_attrname_t. All * on-disk attribute names start with the 8-byte string "SGI_DMI_". * diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h index bef23bbf8690..783c476b8674 100644 --- a/include/linux/fs_enet_pd.h +++ b/include/linux/fs_enet_pd.h @@ -16,7 +16,6 @@ #ifndef FS_ENET_PD_H #define FS_ENET_PD_H -#include #include #define FS_ENET_NAME "fs_enet" diff --git a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h index f25fec8ee2ca..6e5461d69fdd 100644 --- a/include/linux/if_wanpipe_common.h +++ b/include/linux/if_wanpipe_common.h @@ -17,8 +17,6 @@ #ifndef _WANPIPE_SOCK_DRIVER_COMMON_H #define _WANPIPE_SOCK_DRIVER_COMMON_H -#include - typedef struct { struct net_device *slave; atomic_t packet_sent; diff --git a/include/linux/istallion.h b/include/linux/istallion.h index 5f4ee646c119..1f996621bc9c 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h @@ -21,8 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - /*****************************************************************************/ #ifndef _ISTALLION_H #define _ISTALLION_H diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 39f1430bd6d5..3c9ea4b7adda 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -8,7 +8,6 @@ #define __MTD_CFI_H__ #include -#include #include #include #include diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index e95d0463a3e5..b6f2fdae65c6 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -14,7 +14,6 @@ #endif #include -#include #include #include #include diff --git a/include/linux/phonedev.h b/include/linux/phonedev.h index d54049eed0c3..a0e31adf3abe 100644 --- a/include/linux/phonedev.h +++ b/include/linux/phonedev.h @@ -2,7 +2,6 @@ #define __LINUX_PHONEDEV_H #include -#include #ifdef __KERNEL__ diff --git a/include/linux/stallion.h b/include/linux/stallion.h index e89b77b6505a..13a37f137ea2 100644 --- a/include/linux/stallion.h +++ b/include/linux/stallion.h @@ -21,8 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - /*****************************************************************************/ #ifndef _STALLION_H #define _STALLION_H diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c index 4f1ff1bccdce..a7ad2b0a2ac0 100644 --- a/sound/oss/msnd.c +++ b/sound/oss/msnd.c @@ -24,7 +24,6 @@ * ********************************************************************/ -#include #include #include #include diff --git a/sound/oss/os.h b/sound/oss/os.h index 80dce329cc3a..0490562c7f7f 100644 --- a/sound/oss/os.h +++ b/sound/oss/os.h @@ -5,10 +5,8 @@ #undef DO_TIMINGS #include -#include #ifdef __KERNEL__ -#include #include #include #include diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c index 7609c68a89f4..318dc51009fe 100644 --- a/sound/oss/rme96xx.c +++ b/sound/oss/rme96xx.c @@ -44,7 +44,6 @@ TODO: #define RMEVERSION "0.8" #endif -#include #include #include #include diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index c09cdeedc191..8a9917c919c2 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index ae3bb6c6edff..bfff788e9847 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h @@ -22,7 +22,6 @@ #ifndef __PMAC_H #define __PMAC_H -#include #include #include #include "awacs.h" -- cgit v1.2.3 From e4543eddfd3bf3e0d625841377fa695a519edfd4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:04 -0800 Subject: [PATCH] add a vfs_permission helper Most permission() calls have a struct nameidata * available. This helper takes that as an argument and thus makes sure we pass it down for lookup intents and prepares for per-mount read-only support where we need a struct vfsmount for checking whether a file is writeable. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 4 ++-- fs/inotify.c | 2 +- fs/namei.c | 23 +++++++++++++++++++---- fs/namespace.c | 2 +- fs/open.c | 12 ++++++------ include/linux/fs.h | 1 + net/unix/af_unix.c | 2 +- 7 files changed, 31 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/fs/exec.c b/fs/exec.c index 5a4e3acc2e9f..7bbb781b9ac6 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library) if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; - error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); + error = vfs_permission(&nd, MAY_READ | MAY_EXEC); if (error) goto exit; @@ -495,7 +495,7 @@ struct file *open_exec(const char *name) file = ERR_PTR(-EACCES); if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && S_ISREG(inode->i_mode)) { - int err = permission(inode, MAY_EXEC, &nd); + int err = vfs_permission(&nd, MAY_EXEC); if (!err && !(inode->i_mode & 0111)) err = -EACCES; file = ERR_PTR(err); diff --git a/fs/inotify.c b/fs/inotify.c index 9fbaebfdf40b..bf7ce1d2412b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) if (error) return error; /* you can only watch an inode if you have read permissions on it */ - error = permission(nd->dentry->d_inode, MAY_READ, NULL); + error = vfs_permission(nd, MAY_READ); if (error) path_release(nd); return error; diff --git a/fs/namei.c b/fs/namei.c index b3f8a1966c9c..25e4ab4ce8b7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) return security_inode_permission(inode, mask, nd); } +/** + * vfs_permission - check for access rights to a given path + * @nd: lookup result that describes the path + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) + * + * Used to check for read/write/execute permissions on a path. + * We use "fsuid" for this, letting us set arbitrary permissions + * for filesystem access without changing the "normal" uids which + * are used for other things. + */ +int vfs_permission(struct nameidata *nd, int mask) +{ + return permission(nd->dentry->d_inode, mask, nd); +} + /* * get_write_access() gets write permission for a file. * put_write_access() releases this write permission. @@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) nd->flags |= LOOKUP_CONTINUE; err = exec_permission_lite(inode, nd); - if (err == -EAGAIN) { - err = permission(inode, MAY_EXEC, nd); - } + if (err == -EAGAIN) + err = vfs_permission(nd, MAY_EXEC); if (err) break; @@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) return -EISDIR; - error = permission(inode, acc_mode, nd); + error = vfs_permission(nd, acc_mode); if (error) return error; @@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(permission); +EXPORT_SYMBOL(vfs_permission); EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_follow_link); diff --git a/fs/namespace.c b/fs/namespace.c index caa9187f67e5..2019899f2ab8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd) if (current->uid != nd->dentry->d_inode->i_uid) return -EPERM; } - if (permission(nd->dentry->d_inode, MAY_WRITE, nd)) + if (vfs_permission(nd, MAY_WRITE)) return -EPERM; return 0; #endif diff --git a/fs/open.c b/fs/open.c index 6e8136751e9a..baffc084580d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) if (!S_ISREG(inode->i_mode)) goto dput_and_out; - error = permission(inode,MAY_WRITE,&nd); + error = vfs_permission(&nd, MAY_WRITE); if (error) goto dput_and_out; @@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) goto dput_and_out; if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE,&nd)) != 0) + (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } down(&inode->i_sem); @@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times) goto dput_and_out; if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE,&nd)) != 0) + (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } down(&inode->i_sem); @@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode) res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); if (!res) { - res = permission(nd.dentry->d_inode, mode, &nd); + res = vfs_permission(&nd, mode); /* SuS v2 requires we report a read only fs too */ if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) && !special_file(nd.dentry->d_inode->i_mode)) @@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename) if (error) goto out; - error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); + error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; @@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename) if (error) goto out; - error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); + error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; diff --git a/include/linux/fs.h b/include/linux/fs.h index 1b5f502a4b8f..c3b8c1dc7cdf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb) /* * VFS helper functions.. */ +extern int vfs_permission(struct nameidata *, int); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); extern int vfs_mkdir(struct inode *, struct dentry *, int); extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 41feca3bef86..acc73ba8bade 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -676,7 +676,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); if (err) goto fail; - err = permission(nd.dentry->d_inode,MAY_WRITE, &nd); + err = vfs_permission(&nd, MAY_WRITE); if (err) goto put_fail; -- cgit v1.2.3 From 8c744fb83da0771afa04695028e3550b798dad90 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:04 -0800 Subject: [PATCH] add a file_permission helper A few more callers of permission() just want to check for a different access pattern on an already open file. This patch adds a wrapper for permission() that takes a file in preparation of per-mount read-only support and to clean up the callers a little. The helper is not intended for new code, everything without the interface set in stone should use vfs_permission() Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 3 +-- fs/binfmt_misc.c | 2 +- fs/exec.c | 2 +- fs/namei.c | 18 ++++++++++++++++++ fs/ncpfs/ioctl.c | 34 +++++++++++++++++++--------------- fs/open.c | 2 +- fs/udf/file.c | 2 +- include/linux/fs.h | 5 +++++ 8 files changed, 47 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index dd1935d55424..28002de783b6 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3776,8 +3776,7 @@ static int floppy_open(struct inode *inode, struct file *filp) /* Allow ioctls if we have write-permissions even if read-only open. * Needed so that programs such as fdrawcmd still can work on write * protected disks */ - if (filp->f_mode & 2 - || permission(filp->f_dentry->d_inode, 2, NULL) == 0) + if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE)) filp->private_data = (void *)8; if (UFDCS->rawcmd == 1) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 8ae0db6cd69c..2568eb41cb3a 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -150,7 +150,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* if the binary is not readable than enforce mm->dumpable=0 regardless of the interpreter's permissions */ - if (permission(bprm->file->f_dentry->d_inode, MAY_READ, NULL)) + if (file_permission(bprm->file, MAY_READ)) bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; allow_write_access(bprm->file); diff --git a/fs/exec.c b/fs/exec.c index 7bbb781b9ac6..c466fec5de20 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -896,7 +896,7 @@ int flush_old_exec(struct linux_binprm * bprm) flush_thread(); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || - permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || + file_permission(bprm->file, MAY_READ) || (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { suid_keys(current); current->mm->dumpable = suid_dumpable; diff --git a/fs/namei.c b/fs/namei.c index 25e4ab4ce8b7..b69f6ebadb95 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -271,6 +271,23 @@ int vfs_permission(struct nameidata *nd, int mask) return permission(nd->dentry->d_inode, mask, nd); } +/** + * file_permission - check for additional access rights to a given file + * @file: file to check access rights for + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) + * + * Used to check for read/write/execute permissions on an already opened + * file. + * + * Note: + * Do not use this function in new code. All access checks should + * be done using vfs_permission(). + */ +int file_permission(struct file *file, int mask) +{ + return permission(file->f_dentry->d_inode, mask, NULL); +} + /* * get_write_access() gets write permission for a file. * put_write_access() releases this write permission. @@ -2551,6 +2568,7 @@ EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(vfs_permission); +EXPORT_SYMBOL(file_permission); EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_follow_link); diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 88df79356a1f..fd3efdca5ae3 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -30,11 +30,13 @@ #define NCP_PACKET_SIZE_INTERNAL 65536 static int -ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info __user *arg) +ncp_get_fs_info(struct ncp_server * server, struct file *file, + struct ncp_fs_info __user *arg) { + struct inode *inode = file->f_dentry->d_inode; struct ncp_fs_info info; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -58,11 +60,13 @@ ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_in } static int -ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2 __user * arg) +ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, + struct ncp_fs_info_v2 __user * arg) { + struct inode *inode = file->f_dentry->d_inode; struct ncp_fs_info_v2 info2; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -190,7 +194,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, switch (cmd) { case NCP_IOC_NCPREQUEST: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -245,16 +249,16 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return ncp_conn_logged_in(inode->i_sb); case NCP_IOC_GET_FS_INFO: - return ncp_get_fs_info(server, inode, argp); + return ncp_get_fs_info(server, filp, argp); case NCP_IOC_GET_FS_INFO_V2: - return ncp_get_fs_info_v2(server, inode, argp); + return ncp_get_fs_info_v2(server, filp, argp); case NCP_IOC_GETMOUNTUID2: { unsigned long tmp = server->m.mounted_uid; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -268,7 +272,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { struct ncp_setroot_ioctl sr; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -343,7 +347,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_PACKET_SIGNING case NCP_IOC_SIGN_INIT: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -366,7 +370,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; case NCP_IOC_SIGN_WANTED: - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -379,7 +383,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { int newstate; - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -400,7 +404,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_IOCTL_LOCKING case NCP_IOC_LOCKUNLOCK: - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -605,7 +609,7 @@ outrel: #endif /* CONFIG_NCPFS_NLS */ case NCP_IOC_SETDENTRYTTL: - if ((permission(inode, MAY_WRITE, NULL) != 0) && + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) return -EACCES; { @@ -635,7 +639,7 @@ outrel: so we have this out of switch */ if (cmd == NCP_IOC_GETMOUNTUID) { __kernel_uid_t uid = 0; - if ((permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } diff --git a/fs/open.c b/fs/open.c index baffc084580d..f53a5b9ffb7d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -563,7 +563,7 @@ asmlinkage long sys_fchdir(unsigned int fd) if (!S_ISDIR(inode->i_mode)) goto out_putf; - error = permission(inode, MAY_EXEC, NULL); + error = file_permission(file, MAY_EXEC); if (!error) set_fs_pwd(current->fs, mnt, dentry); out_putf: diff --git a/fs/udf/file.c b/fs/udf/file.c index bb40d63f328f..01f520c71dc1 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -186,7 +186,7 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, { int result = -EINVAL; - if ( permission(inode, MAY_READ, NULL) != 0 ) + if ( file_permission(filp, MAY_READ) != 0 ) { udf_debug("no permission to access inode %lu\n", inode->i_ino); diff --git a/include/linux/fs.h b/include/linux/fs.h index c3b8c1dc7cdf..cc35b6ac778d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -889,6 +889,11 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de */ extern void dentry_unhash(struct dentry *dentry); +/* + * VFS file helper functions. + */ +extern int file_permission(struct file *, int); + /* * File types * -- cgit v1.2.3 From 49705b7743fd8f5632a95ec4c6547d169d27ac1f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:06 -0800 Subject: [PATCH] sanitize lookup_hash prototype ->permission and ->lookup have a struct nameidata * argument these days to pass down lookup intents. Unfortunately some callers of lookup_hash don't actually pass this one down. For lookup_one_len() we don't have a struct nameidata to pass down, but as this function is a library function only used by filesystem code this is an acceptable limitation. All other callers should pass down the nameidata, so this patch changes the lookup_hash interface to only take a struct nameidata argument and derives the other two arguments to __lookup_hash from it. All callers already have the nameidata argument available so this is not a problem. At the same time I'd like to deprecate the lookup_hash interface as there are better exported interfaces for filesystem usage. Before it can actually be removed I need to fix up rpc_pipefs. Signed-off-by: Christoph Hellwig Cc: Ram Pai Cc: Jeff Mahoney Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 7 +++++++ fs/namei.c | 20 ++++++++++---------- include/linux/namei.h | 2 +- net/sunrpc/rpc_pipe.c | 6 +++--- 4 files changed, 21 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 910cc9998731..66e4ca28fc0a 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -118,3 +118,10 @@ Why: This interface has been obsoleted by the new layer3-independent to link against API-compatible library on top of libnfnetlink_queue instead of the current 'libipq'. Who: Harald Welte + +--------------------------- + +What: EXPORT_SYMBOL(lookup_hash) +When: January 2006 +Why: Too low-level interface. Use lookup_one_len or lookup_create instead. +Who: Christoph Hellwig diff --git a/fs/namei.c b/fs/namei.c index b69f6ebadb95..f02ec0e50fca 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1204,9 +1204,9 @@ out: return dentry; } -struct dentry * lookup_hash(struct qstr *name, struct dentry * base) +struct dentry * lookup_hash(struct nameidata *nd) { - return __lookup_hash(name, base, NULL); + return __lookup_hash(&nd->last, nd->dentry, nd); } /* SMP-safe */ @@ -1230,7 +1230,7 @@ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) } this.hash = end_name_hash(hash); - return lookup_hash(&this, base); + return __lookup_hash(&this, base, NULL); access: return ERR_PTR(-EACCES); } @@ -1563,7 +1563,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) dir = nd->dentry; nd->flags &= ~LOOKUP_PARENT; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); + path.dentry = lookup_hash(nd); path.mnt = nd->mnt; do_last: @@ -1665,7 +1665,7 @@ do_link: } dir = nd->dentry; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); + path.dentry = lookup_hash(nd); path.mnt = nd->mnt; __putname(nd->last.name); goto do_last; @@ -1697,7 +1697,7 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) /* * Do the final lookup. */ - dentry = lookup_hash(&nd->last, nd->dentry); + dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto fail; @@ -1932,7 +1932,7 @@ asmlinkage long sys_rmdir(const char __user * pathname) goto exit1; } down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); @@ -2001,7 +2001,7 @@ asmlinkage long sys_unlink(const char __user * pathname) if (nd.last_type != LAST_NORM) goto exit1; down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ @@ -2344,7 +2344,7 @@ static inline int do_rename(const char * oldname, const char * newname) trap = lock_rename(new_dir, old_dir); - old_dentry = lookup_hash(&oldnd.last, old_dir); + old_dentry = lookup_hash(&oldnd); error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; @@ -2364,7 +2364,7 @@ static inline int do_rename(const char * oldname, const char * newname) error = -EINVAL; if (old_dentry == trap) goto exit4; - new_dentry = lookup_hash(&newnd.last, new_dir); + new_dentry = lookup_hash(&newnd); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto exit4; diff --git a/include/linux/namei.h b/include/linux/namei.h index 1c975d0d9e94..455660eafba9 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -74,7 +74,7 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); extern void release_open_intent(struct nameidata *); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -extern struct dentry * lookup_hash(struct qstr *, struct dentry *); +extern struct dentry * lookup_hash(struct nameidata *); extern int follow_down(struct vfsmount **, struct dentry **); extern int follow_up(struct vfsmount **, struct dentry **); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 4f188d0a5d11..81e00a6c19de 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -603,7 +603,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) return ERR_PTR(error); dir = nd->dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd->last, nd->dentry); + dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto out_err; if (dentry->d_inode) { @@ -665,7 +665,7 @@ rpc_rmdir(char *path) return error; dir = nd.dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; @@ -726,7 +726,7 @@ rpc_unlink(char *path) return error; dir = nd.dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; -- cgit v1.2.3 From b05a581d4865d74c0e270d27156a88d2dee9494e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:08 -0800 Subject: [PATCH] move some COMPATIBLE_IOCTL entries from x86_64 to common code Signed-off-by: Christoph Hellwig Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/ia32_ioctl.c | 6 ------ include/linux/compat_ioctl.h | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 4ba0e293d5e5..e335bd0b637d 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -64,12 +64,6 @@ struct ioctl_trans ioctl_start[] = { #include #define DECLARES #include "compat_ioctl.c" -COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) -COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ /* realtime device */ diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index ecb0d39c0798..4c63c2963019 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -10,6 +10,10 @@ #define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl) #endif + +COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ +COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ + /* Big T */ COMPATIBLE_IOCTL(TCGETA) COMPATIBLE_IOCTL(TCSETA) @@ -81,6 +85,8 @@ COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) COMPATIBLE_IOCTL(HDIO_DRIVE_TASK) COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) COMPATIBLE_IOCTL(HDIO_SET_NICE) +COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) +COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) /* 0x02 -- Floppy ioctls */ COMPATIBLE_IOCTL(FDMSGON) COMPATIBLE_IOCTL(FDMSGOFF) @@ -99,6 +105,7 @@ COMPATIBLE_IOCTL(FDTWADDLE) COMPATIBLE_IOCTL(FDFMTTRK) COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ +COMPATIBLE_IOCTL(BLKRASET) COMPATIBLE_IOCTL(BLKROSET) COMPATIBLE_IOCTL(BLKROGET) COMPATIBLE_IOCTL(BLKRRPART) @@ -262,6 +269,7 @@ COMPATIBLE_IOCTL(RTC_WKALM_RD) /* Little m */ COMPATIBLE_IOCTL(MTIOCTOP) /* Socket level stuff */ +COMPATIBLE_IOCTL(FIOQSIZE) COMPATIBLE_IOCTL(FIOSETOWN) COMPATIBLE_IOCTL(SIOCSPGRP) COMPATIBLE_IOCTL(FIOGETOWN) -- cgit v1.2.3 From 93df3413f1b4c437b93c5b64562632f4f0e2b3ca Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:36:31 -0800 Subject: [PATCH] v4l: 655: added support for the philips td1316 tuner - Added support for the Philips TD1316 tuner Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-core.c | 7 +++++++ drivers/media/video/tuner-simple.c | 2 ++ include/media/tuner.h | 1 + 3 files changed, 10 insertions(+) (limited to 'include') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index ad85bef1c3d5..949c2550fcf5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -189,6 +189,13 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c, buffer, 4); default_tuner_init(c); break; + case TUNER_PHILIPS_TD1316: + buffer[0] = 0x0b; + buffer[1] = 0xdc; + buffer[2] = 0x86; + buffer[3] = 0xa4; + i2c_master_send(c,buffer,4); + default_tuner_init(c); default: default_tuner_init(c); break; diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 0ae39be3ca56..3af055970dd2 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -248,6 +248,8 @@ static struct tunertype tuners[] = { 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, + { "Philips TD1316 Hybrid Tuner", Philips, PAL, + 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index 4ad08e24a1aa..4f47eac90caf 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -110,6 +110,7 @@ #define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */ #define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */ #define TUNER_LG_NTSC_TALN_MINI 66 +#define TUNER_PHILIPS_TD1316 67 #define NOTUNER 0 #define PAL 1 /* PAL_BG */ -- cgit v1.2.3 From 20f441f6900d786606583263d89653c48c7093a8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:36:44 -0800 Subject: [PATCH] v4l: 685: update the tveeprom tuner list with the tuner - Update the tveeprom tuner list with the tuner Signed-off-by: Hans Verkuil Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-simple.c | 4 ++-- drivers/media/video/tveeprom.c | 22 ++++++++++++++-------- include/media/tuner.h | 2 +- 3 files changed, 17 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3af055970dd2..b75ad2d4488a 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -222,7 +222,7 @@ static struct tunertype tuners[] = { 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, /* UHF band untested */ { "tda8290+75", Philips, PAL|NTSC, /* see tda8290.c for details */ }, - { "LG PAL (TAPE series)", LGINNOTEK, PAL, + { "TCL 2002MB", TCL, PAL, 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, @@ -233,7 +233,7 @@ static struct tunertype tuners[] = { { "Ymec TVision TVF-5533MF", Philips, NTSC, 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, - /* 60-66 */ + /* 60-67 */ { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 5344d5592199..6453b71f2997 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -200,15 +200,21 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Philips FQ1286A MK4"}, { TUNER_ABSENT, "Philips FQ1216ME MK5"}, { TUNER_ABSENT, "Philips FQ1236 MK5"}, - { TUNER_ABSENT, "Unspecified"}, - { TUNER_LG_PAL_TAPE, "LG PAL (TAPE Series)"}, - { TUNER_ABSENT, "Unspecified"}, + { TUNER_ABSENT, "Samsung TCPG_6121P30A"}, + { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, + { TUNER_ABSENT, "TCL 2002MI_3H"}, { TUNER_TCL_2002N, "TCL 2002N 5H"}, - /* 100-103 */ - { TUNER_ABSENT, "Unspecified"}, - { TUNER_TEA5767, "Philips TEA5767HN FM Radio"}, - { TUNER_ABSENT, "Unspecified"}, - { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05 4"}, + /* 100-109 */ + { TUNER_ABSENT, "Philips FMD1216ME"}, + { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, + { TUNER_ABSENT, "Panasonic ENV57H12D5"}, + { TUNER_ABSENT, "TCL MFNM05-4"}, + { TUNER_ABSENT, "TCL MNM05-4"}, + { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, + { TUNER_ABSENT, "TCL MQNM05-4"}, + { TUNER_ABSENT, "LG TAPC-W701D"}, + { TUNER_ABSENT, "TCL 9886P-WM"}, + { TUNER_ABSENT, "TCL 1676NM-WM"}, }; /* This list is supplied by Hauppauge. Thanks! */ diff --git a/include/media/tuner.h b/include/media/tuner.h index 4f47eac90caf..bf925702fbbf 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -95,7 +95,7 @@ #define TUNER_THOMSON_DTT7610 52 #define TUNER_PHILIPS_FQ1286 53 #define TUNER_PHILIPS_TDA8290 54 -#define TUNER_LG_PAL_TAPE 55 /* Hauppauge PVR-150 PAL */ +#define TUNER_TCL_2002MB 55 /* Hauppauge PVR-150 PAL */ #define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ #define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ -- cgit v1.2.3 From 70b6934a6c6b5f242a42978f3c5e4f45d476dddb Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:50 -0800 Subject: [PATCH] v4l: 691: set if of tda8275 according to tv norm - Set IF of tda8275 according to tv norm. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 21 ++++++++++++++------- include/media/tuner.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 61268f8a9eec..1e2acc4abbe6 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -181,18 +181,25 @@ static void set_audio(struct tuner *t) { t->i2c_easy_mode[0] = 0x01; - if (t->std & V4L2_STD_MN) + if (t->std & V4L2_STD_MN) { + t->sgIF = 736; t->i2c_easy_mode[1] = 0x01; - else if (t->std & V4L2_STD_B) + } else if (t->std & V4L2_STD_B) { + t->sgIF = 864; t->i2c_easy_mode[1] = 0x02; - else if (t->std & V4L2_STD_GH) + } else if (t->std & V4L2_STD_GH) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x04; - else if (t->std & V4L2_STD_PAL_I) + } else if (t->std & V4L2_STD_PAL_I) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x08; - else if (t->std & V4L2_STD_DK) + } else if (t->std & V4L2_STD_DK) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x10; - else if (t->std & V4L2_STD_SECAM_L) + } else if (t->std & V4L2_STD_SECAM_L) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x20; + } } static void set_tv_freq(struct i2c_client *c, unsigned int freq) @@ -200,7 +207,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); set_audio(t); - set_frequency(t, 864, freq); + set_frequency(t, t->sgIF, freq); tda8290_tune(c); } diff --git a/include/media/tuner.h b/include/media/tuner.h index bf925702fbbf..97e16bddf651 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -191,6 +191,7 @@ struct tuner { /* used by tda8290 */ unsigned char i2c_easy_mode[2]; unsigned char i2c_set_freq[8]; + unsigned int sgIF; /* function ptrs */ void (*tv_freq)(struct i2c_client *c, unsigned int freq); -- cgit v1.2.3 From 90a7ed47a37297bee1f4ce11484190ccac29ae7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:56 -0800 Subject: [PATCH] v4l: 702: included audio chips enum - Included audio chips enum Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tveeprom.c | 432 +++++++++++++++++++++++------------------ include/media/audiochip.h | 17 ++ 2 files changed, 264 insertions(+), 185 deletions(-) (limited to 'include') diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 6453b71f2997..a9bad89b4d69 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -40,6 +40,7 @@ #include #include +#include "audiochip.h" MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); MODULE_AUTHOR("John Klar"); @@ -134,8 +135,8 @@ hauppauge_tuner[] = { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" }, { TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" }, { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" }, - { TUNER_PHILIPS_NTSC, "Philips TD1536" }, - { TUNER_PHILIPS_NTSC, "Philips TD1536D" }, + { TUNER_PHILIPS_NTSC, "Philips TD1536" }, + { TUNER_PHILIPS_NTSC, "Philips TD1536D" }, { TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */ { TUNER_ABSENT, "Philips FI1256MP" }, /* 40-49 */ @@ -189,7 +190,7 @@ hauppauge_tuner[] = { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"}, { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"}, { TUNER_TCL_2002N, "TCL 2002N 6A"}, - { TUNER_ABSENT, "Philips FQ1236 MK3"}, + { TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"}, { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"}, @@ -202,93 +203,129 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Philips FQ1236 MK5"}, { TUNER_ABSENT, "Samsung TCPG_6121P30A"}, { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, - { TUNER_ABSENT, "TCL 2002MI_3H"}, - { TUNER_TCL_2002N, "TCL 2002N 5H"}, + { TUNER_ABSENT, "TCL 2002MI_3H"}, + { TUNER_TCL_2002N, "TCL 2002N 5H"}, /* 100-109 */ { TUNER_ABSENT, "Philips FMD1216ME"}, - { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, - { TUNER_ABSENT, "Panasonic ENV57H12D5"}, - { TUNER_ABSENT, "TCL MFNM05-4"}, - { TUNER_ABSENT, "TCL MNM05-4"}, - { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, - { TUNER_ABSENT, "TCL MQNM05-4"}, - { TUNER_ABSENT, "LG TAPC-W701D"}, - { TUNER_ABSENT, "TCL 9886P-WM"}, - { TUNER_ABSENT, "TCL 1676NM-WM"}, + { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, + { TUNER_ABSENT, "Panasonic ENV57H12D5"}, + { TUNER_ABSENT, "TCL MFNM05-4"}, + { TUNER_ABSENT, "TCL MNM05-4"}, + { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, + { TUNER_ABSENT, "TCL MQNM05-4"}, + { TUNER_ABSENT, "LG TAPC-W701D"}, + { TUNER_ABSENT, "TCL 9886P-WM"}, + { TUNER_ABSENT, "TCL 1676NM-WM"}, }; -/* This list is supplied by Hauppauge. Thanks! */ -static const char *audioIC[] = { - /* 0-4 */ - "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C", - /* 5-9 */ - "MSP3410D", "MSP3415", "MSP3430", "MSP3438", "CS5331", - /* 10-14 */ - "MSP3435", "MSP3440", "MSP3445", "MSP3411", "MSP3416", - /* 15-19 */ - "MSP3425", "MSP3451", "MSP3418", "Type 0x12", "OKI7716", - /* 20-24 */ - "MSP4410", "MSP4420", "MSP4440", "MSP4450", "MSP4408", - /* 25-29 */ - "MSP4418", "MSP4428", "MSP4448", "MSP4458", "Type 0x1d", - /* 30-34 */ - "CX880", "CX881", "CX883", "CX882", "CX25840", - /* 35-38 */ - "CX25841", "CX25842", "CX25843", "CX23418", +static struct HAUPPAUGE_AUDIOIC +{ + enum audiochip id; + char *name; +} +audioIC[] = +{ + /* 0-4 */ + {AUDIO_CHIP_NONE, "None"}, + {AUDIO_CHIP_TEA6300, "TEA6300"}, + {AUDIO_CHIP_TEA6300, "TEA6320"}, + {AUDIO_CHIP_TDA985X, "TDA9850"}, + {AUDIO_CHIP_MSP34XX, "MSP3400C"}, + /* 5-9 */ + {AUDIO_CHIP_MSP34XX, "MSP3410D"}, + {AUDIO_CHIP_MSP34XX, "MSP3415"}, + {AUDIO_CHIP_MSP34XX, "MSP3430"}, + {AUDIO_CHIP_UNKNOWN, "MSP3438"}, + {AUDIO_CHIP_UNKNOWN, "CS5331"}, + /* 10-14 */ + {AUDIO_CHIP_MSP34XX, "MSP3435"}, + {AUDIO_CHIP_MSP34XX, "MSP3440"}, + {AUDIO_CHIP_MSP34XX, "MSP3445"}, + {AUDIO_CHIP_UNKNOWN, "MSP3411"}, + {AUDIO_CHIP_UNKNOWN, "MSP3416"}, + /* 15-19 */ + {AUDIO_CHIP_MSP34XX, "MSP3425"}, + {AUDIO_CHIP_UNKNOWN, "MSP3451"}, + {AUDIO_CHIP_UNKNOWN, "MSP3418"}, + {AUDIO_CHIP_UNKNOWN, "Type 0x12"}, + {AUDIO_CHIP_UNKNOWN, "OKI7716"}, + /* 20-24 */ + {AUDIO_CHIP_UNKNOWN, "MSP4410"}, + {AUDIO_CHIP_UNKNOWN, "MSP4420"}, + {AUDIO_CHIP_UNKNOWN, "MSP4440"}, + {AUDIO_CHIP_UNKNOWN, "MSP4450"}, + {AUDIO_CHIP_UNKNOWN, "MSP4408"}, + /* 25-29 */ + {AUDIO_CHIP_UNKNOWN, "MSP4418"}, + {AUDIO_CHIP_UNKNOWN, "MSP4428"}, + {AUDIO_CHIP_UNKNOWN, "MSP4448"}, + {AUDIO_CHIP_UNKNOWN, "MSP4458"}, + {AUDIO_CHIP_UNKNOWN, "Type 0x1d"}, + /* 30-34 */ + {AUDIO_CHIP_INTERNAL, "CX880"}, + {AUDIO_CHIP_INTERNAL, "CX881"}, + {AUDIO_CHIP_INTERNAL, "CX883"}, + {AUDIO_CHIP_INTERNAL, "CX882"}, + {AUDIO_CHIP_INTERNAL, "CX25840"}, + /* 35-38 */ + {AUDIO_CHIP_INTERNAL, "CX25841"}, + {AUDIO_CHIP_INTERNAL, "CX25842"}, + {AUDIO_CHIP_INTERNAL, "CX25843"}, + {AUDIO_CHIP_INTERNAL, "CX23418"}, }; /* This list is supplied by Hauppauge. Thanks! */ static const char *decoderIC[] = { - /* 0-4 */ - "None", "BT815", "BT817", "BT819", "BT815A", - /* 5-9 */ - "BT817A", "BT819A", "BT827", "BT829", "BT848", - /* 10-14 */ - "BT848A", "BT849A", "BT829A", "BT827A", "BT878", - /* 15-19 */ - "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115", - /* 20-24 */ - "CX880", "CX881", "CX883", "SAA7111", "SAA7113", - /* 25-29 */ - "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", - /* 30-31 */ - "CX25843", "CX23418", + /* 0-4 */ + "None", "BT815", "BT817", "BT819", "BT815A", + /* 5-9 */ + "BT817A", "BT819A", "BT827", "BT829", "BT848", + /* 10-14 */ + "BT848A", "BT849A", "BT829A", "BT827A", "BT878", + /* 15-19 */ + "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115", + /* 20-24 */ + "CX880", "CX881", "CX883", "SAA7111", "SAA7113", + /* 25-29 */ + "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", + /* 30-31 */ + "CX25843", "CX23418", }; static int hasRadioTuner(int tunerType) { switch (tunerType) { - case 18: //PNPEnv_TUNER_FR1236_MK2: - case 23: //PNPEnv_TUNER_FM1236: - case 38: //PNPEnv_TUNER_FMR1236: - case 16: //PNPEnv_TUNER_FR1216_MK2: - case 19: //PNPEnv_TUNER_FR1246_MK2: - case 21: //PNPEnv_TUNER_FM1216: - case 24: //PNPEnv_TUNER_FM1246: - case 17: //PNPEnv_TUNER_FR1216MF_MK2: - case 22: //PNPEnv_TUNER_FM1216MF: - case 20: //PNPEnv_TUNER_FR1256_MK2: - case 25: //PNPEnv_TUNER_FM1256: - case 33: //PNPEnv_TUNER_4039FR5: - case 42: //PNPEnv_TUNER_4009FR5: - case 52: //PNPEnv_TUNER_4049FM5: - case 54: //PNPEnv_TUNER_4049FM5_AltI2C: - case 44: //PNPEnv_TUNER_4009FN5: - case 31: //PNPEnv_TUNER_TCPB9085P: - case 30: //PNPEnv_TUNER_TCPN9085D: - case 46: //PNPEnv_TUNER_TP18NSR01F: - case 47: //PNPEnv_TUNER_TP18PSB01D: - case 49: //PNPEnv_TUNER_TAPC_I001D: - case 60: //PNPEnv_TUNER_TAPE_S001D_MK3: - case 57: //PNPEnv_TUNER_FM1216ME_MK3: - case 59: //PNPEnv_TUNER_FM1216MP_MK3: - case 58: //PNPEnv_TUNER_FM1236_MK3: - case 68: //PNPEnv_TUNER_TAPE_H001F_MK3: - case 61: //PNPEnv_TUNER_TAPE_M001D_MK3: - case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM: - case 89: //PNPEnv_TUNER_TCL_MFPE05_2: - case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: - return 1; + case 18: //PNPEnv_TUNER_FR1236_MK2: + case 23: //PNPEnv_TUNER_FM1236: + case 38: //PNPEnv_TUNER_FMR1236: + case 16: //PNPEnv_TUNER_FR1216_MK2: + case 19: //PNPEnv_TUNER_FR1246_MK2: + case 21: //PNPEnv_TUNER_FM1216: + case 24: //PNPEnv_TUNER_FM1246: + case 17: //PNPEnv_TUNER_FR1216MF_MK2: + case 22: //PNPEnv_TUNER_FM1216MF: + case 20: //PNPEnv_TUNER_FR1256_MK2: + case 25: //PNPEnv_TUNER_FM1256: + case 33: //PNPEnv_TUNER_4039FR5: + case 42: //PNPEnv_TUNER_4009FR5: + case 52: //PNPEnv_TUNER_4049FM5: + case 54: //PNPEnv_TUNER_4049FM5_AltI2C: + case 44: //PNPEnv_TUNER_4009FN5: + case 31: //PNPEnv_TUNER_TCPB9085P: + case 30: //PNPEnv_TUNER_TCPN9085D: + case 46: //PNPEnv_TUNER_TP18NSR01F: + case 47: //PNPEnv_TUNER_TP18PSB01D: + case 49: //PNPEnv_TUNER_TAPC_I001D: + case 60: //PNPEnv_TUNER_TAPE_S001D_MK3: + case 57: //PNPEnv_TUNER_FM1216ME_MK3: + case 59: //PNPEnv_TUNER_FM1216MP_MK3: + case 58: //PNPEnv_TUNER_FM1236_MK3: + case 68: //PNPEnv_TUNER_TAPE_H001F_MK3: + case 61: //PNPEnv_TUNER_TAPE_M001D_MK3: + case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM: + case 89: //PNPEnv_TUNER_TCL_MFPE05_2: + case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: + return 1; } return 0; } @@ -318,19 +355,27 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, ** # of inputs/outputs ??? */ - int i, j, len, done, beenhere, tag; + int i, j, len, done, beenhere, tag,start; - int tuner1 = 0, t_format1 = 0; + int tuner1 = 0, t_format1 = 0, audioic=-1; char *t_name1 = NULL; - const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; + const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; - int tuner2 = 0, t_format2 = 0; + int tuner2 = 0, t_format2 = 0; char *t_name2 = NULL; - const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; + const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; - memset(tvee, 0, sizeof(*tvee)); + memset(tvee, 0, sizeof(*tvee)); done = len = beenhere = 0; - for (i = 0; !done && i < 256; i += len) { + + /* Hack for processing eeprom for em28xx */ + if ((eeprom_data[0]==0x1a)&&(eeprom_data[1]==0xeb)&& + (eeprom_data[2]==0x67)&&(eeprom_data[3]==0x95)) + start=0xa0; + else + start=0; + + for (i = start; !done && i < 256; i += len) { if (eeprom_data[i] == 0x84) { len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8); i += 3; @@ -344,28 +389,28 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, ++i; } else { tveeprom_warn("Encountered bad packet header [%02x]. " - "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]); + "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]); return; } - if (debug) { - tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1); - for(j = 1; j < len; j++) { - printk(" %02x", eeprom_data[i + j]); - } - printk("\n"); - } + if (debug) { + tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1); + for(j = 1; j < len; j++) { + printk(" %02x", eeprom_data[i + j]); + } + printk("\n"); + } /* process by tag */ tag = eeprom_data[i]; switch (tag) { case 0x00: - /* tag: 'Comprehensive' */ + /* tag: 'Comprehensive' */ tuner1 = eeprom_data[i+6]; t_format1 = eeprom_data[i+5]; tvee->has_radio = eeprom_data[i+len-1]; - /* old style tag, don't know how to detect - IR presence, mark as unknown. */ + /* old style tag, don't know how to detect + IR presence, mark as unknown. */ tvee->has_ir = 2; tvee->model = eeprom_data[i+8] + @@ -376,7 +421,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x01: - /* tag: 'SerialID' */ + /* tag: 'SerialID' */ tvee->serial_number = eeprom_data[i+6] + (eeprom_data[i+7] << 8) + @@ -384,17 +429,21 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x02: - /* tag 'AudioInfo' - Note mask with 0x7F, high bit used on some older models - to indicate 4052 mux was removed in favor of using MSP - inputs directly. */ - tvee->audio_processor = eeprom_data[i+2] & 0x7f; + /* tag 'AudioInfo' + Note mask with 0x7F, high bit used on some older models + to indicate 4052 mux was removed in favor of using MSP + inputs directly. */ + audioic = eeprom_data[i+2] & 0x7f; + if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + tvee->audio_processor = audioIC[audioic].id; + else + tvee->audio_processor = AUDIO_CHIP_UNKNOWN; break; - /* case 0x03: tag 'EEInfo' */ + /* case 0x03: tag 'EEInfo' */ case 0x04: - /* tag 'SerialID2' */ + /* tag 'SerialID2' */ tvee->serial_number = eeprom_data[i+5] + (eeprom_data[i+6] << 8) + @@ -402,15 +451,20 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x05: - /* tag 'Audio2' - Note mask with 0x7F, high bit used on some older models - to indicate 4052 mux was removed in favor of using MSP - inputs directly. */ - tvee->audio_processor = eeprom_data[i+1] & 0x7f; + /* tag 'Audio2' + Note mask with 0x7F, high bit used on some older models + to indicate 4052 mux was removed in favor of using MSP + inputs directly. */ + audioic = eeprom_data[i+1] & 0x7f; + if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + tvee->audio_processor = audioIC[audioic].id; + else + tvee->audio_processor = AUDIO_CHIP_UNKNOWN; + break; case 0x06: - /* tag 'ModelRev' */ + /* tag 'ModelRev' */ tvee->model = eeprom_data[i+1] + (eeprom_data[i+2] << 8); @@ -420,55 +474,55 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x07: - /* tag 'Details': according to Hauppauge not interesting - on any PCI-era or later boards. */ + /* tag 'Details': according to Hauppauge not interesting + on any PCI-era or later boards. */ break; - /* there is no tag 0x08 defined */ + /* there is no tag 0x08 defined */ case 0x09: - /* tag 'Video' */ + /* tag 'Video' */ tvee->decoder_processor = eeprom_data[i + 1]; break; case 0x0a: - /* tag 'Tuner' */ + /* tag 'Tuner' */ if (beenhere == 0) { tuner1 = eeprom_data[i+2]; t_format1 = eeprom_data[i+1]; beenhere = 1; } else { - /* a second (radio) tuner may be present */ + /* a second (radio) tuner may be present */ tuner2 = eeprom_data[i+2]; t_format2 = eeprom_data[i+1]; - if (t_format2 == 0) { /* not a TV tuner? */ - tvee->has_radio = 1; /* must be radio */ - } - } + if (t_format2 == 0) { /* not a TV tuner? */ + tvee->has_radio = 1; /* must be radio */ + } + } break; - case 0x0b: - /* tag 'Inputs': according to Hauppauge this is specific - to each driver family, so no good assumptions can be - made. */ - break; + case 0x0b: + /* tag 'Inputs': according to Hauppauge this is specific + to each driver family, so no good assumptions can be + made. */ + break; - /* case 0x0c: tag 'Balun' */ - /* case 0x0d: tag 'Teletext' */ + /* case 0x0c: tag 'Balun' */ + /* case 0x0d: tag 'Teletext' */ case 0x0e: - /* tag: 'Radio' */ + /* tag: 'Radio' */ tvee->has_radio = eeprom_data[i+1]; break; - case 0x0f: - /* tag 'IRInfo' */ - tvee->has_ir = eeprom_data[i+1]; - break; + case 0x0f: + /* tag 'IRInfo' */ + tvee->has_ir = eeprom_data[i+1]; + break; - /* case 0x10: tag 'VBIInfo' */ - /* case 0x11: tag 'QCInfo' */ - /* case 0x12: tag 'InfoBits' */ + /* case 0x10: tag 'VBIInfo' */ + /* case 0x11: tag 'QCInfo' */ + /* case 0x12: tag 'InfoBits' */ default: tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag); @@ -489,11 +543,11 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->rev_str[4] = 0; } - if (hasRadioTuner(tuner1) && !tvee->has_radio) { - tveeprom_info("The eeprom says no radio is present, but the tuner type\n"); - tveeprom_info("indicates otherwise. I will assume that radio is present.\n"); - tvee->has_radio = 1; - } + if (hasRadioTuner(tuner1) && !tvee->has_radio) { + tveeprom_info("The eeprom says no radio is present, but the tuner type\n"); + tveeprom_info("indicates otherwise. I will assume that radio is present.\n"); + tvee->has_radio = 1; + } if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { tvee->tuner_type = hauppauge_tuner[tuner1].id; @@ -516,45 +570,53 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->tuner_formats |= hauppauge_tuner_fmt[i].id; t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name; } - if (t_format2 & (1 << i)) { - tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id; - t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name; - } + if (t_format2 & (1 << i)) { + tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id; + t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name; + } } tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n", - tvee->model, tvee->rev_str, tvee->serial_number); + tvee->model, tvee->rev_str, tvee->serial_number); tveeprom_info("tuner model is %s (idx %d, type %d)\n", - t_name1, tuner1, tvee->tuner_type); + t_name1, tuner1, tvee->tuner_type); tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", - t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3], - t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7], - t_format1); - if (tuner2) { - tveeprom_info("second tuner model is %s (idx %d, type %d)\n", - t_name2, tuner2, tvee->tuner2_type); - } - if (t_format2) { - tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", - t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3], - t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7], - t_format2); - } - tveeprom_info("audio processor is %s (idx %d)\n", - STRM(audioIC, tvee->audio_processor), - tvee->audio_processor); - if (tvee->decoder_processor) { - tveeprom_info("decoder processor is %s (idx %d)\n", - STRM(decoderIC, tvee->decoder_processor), - tvee->decoder_processor); - } - if (tvee->has_ir == 2) - tveeprom_info("has %sradio\n", - tvee->has_radio ? "" : "no "); - else - tveeprom_info("has %sradio, has %sIR remote\n", - tvee->has_radio ? "" : "no ", - tvee->has_ir ? "" : "no "); + t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3], + t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7], + t_format1); + if (tuner2) { + tveeprom_info("second tuner model is %s (idx %d, type %d)\n", + t_name2, tuner2, tvee->tuner2_type); + } + if (t_format2) { + tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", + t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3], + t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7], + t_format2); + } + if (audioic<0) { + tveeprom_info("audio processor is unknown (no idx)\n"); + tvee->audio_processor=AUDIO_CHIP_UNKNOWN; + } else { + if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + tveeprom_info("audio processor is %s (idx %d)\n", + audioIC[audioic].name,audioic); + else + tveeprom_info("audio processor is unknown (idx %d)\n", + audioic); + } + if (tvee->decoder_processor) { + tveeprom_info("decoder processor is %s (idx %d)\n", + STRM(decoderIC, tvee->decoder_processor), + tvee->decoder_processor); + } + if (tvee->has_ir == 2) + tveeprom_info("has %sradio\n", + tvee->has_radio ? "" : "no "); + else + tveeprom_info("has %sradio, has %sIR remote\n", + tvee->has_radio ? "" : "no ", + tvee->has_ir ? "" : "no "); } EXPORT_SYMBOL(tveeprom_hauppauge_analog); @@ -575,18 +637,18 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len) tveeprom_warn("i2c eeprom read error (err=%d)\n", err); return -1; } - if (debug) { - int i; - - tveeprom_info("full 256-byte eeprom dump:\n"); - for (i = 0; i < len; i++) { - if (0 == (i % 16)) - tveeprom_info("%02x:", i); - printk(" %02x", eedata[i]); - if (15 == (i % 16)) - printk("\n"); - } - } + if (debug) { + int i; + + tveeprom_info("full 256-byte eeprom dump:\n"); + for (i = 0; i < len; i++) { + if (0 == (i % 16)) + tveeprom_info("%02x:", i); + printk(" %02x", eedata[i]); + if (15 == (i % 16)) + printk("\n"); + } + } return 0; } EXPORT_SYMBOL(tveeprom_read); diff --git a/include/media/audiochip.h b/include/media/audiochip.h index a7ceee9fc5e9..dd1e484e86d3 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -4,6 +4,23 @@ #ifndef AUDIOCHIP_H #define AUDIOCHIP_H +enum audiochip { + AUDIO_CHIP_NONE, + AUDIO_CHIP_UNKNOWN, + /* Provided by video chip */ + AUDIO_CHIP_INTERNAL, + /* Provided by tvaudio.c */ + AUDIO_CHIP_TDA8425, + AUDIO_CHIP_TEA6300, + AUDIO_CHIP_TEA6420, + AUDIO_CHIP_TDA9840, + AUDIO_CHIP_TDA985X, + AUDIO_CHIP_TDA9874, + AUDIO_CHIP_PIC16C54, + /* Provided by msp3400.c */ + AUDIO_CHIP_MSP34XX +}; + /* ---------------------------------------------------------------------- */ /* v4l device was opened in Radio mode */ -- cgit v1.2.3 From e976f93725ce16b4a493d40a6dd3bccbd74b9a8a Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:37:04 -0800 Subject: [PATCH] v4l: 712: added analog support for ati hdtv wonder - Added analog support for ATI HDTV Wonder Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 1 + Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/video/cx88/cx88-cards.c | 49 ++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + drivers/media/video/tuner-simple.c | 15 +++++++++- include/media/tuner.h | 2 ++ 6 files changed, 68 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 8a14e3f44ca2..ca46fbf489d5 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -32,3 +32,4 @@ 31 -> DViCO FusionHDTV 5 Gold [18ac:d500] 32 -> AverMedia UltraTV Media Center PCI 550 [1461:8011] 33 -> Kworld V-Stream Xpert DVD + 34 -> ATI HDTV Wonder [1002:a101] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 0e2ea497ad7f..ec840ca6f455 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -66,3 +66,4 @@ tuner=64 - LG TDVS-H062F/TUA6034 tuner=65 - Ymec TVF66T5-B/DFF tuner=66 - LG NTSC (TALN mini series) tuner=67 - Philips TD1316 Hybrid Tuner +tuner=68 - Philips TUV1236D ATSC/NTSC dual in diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 888d25d48416..388440789dfb 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -823,6 +823,35 @@ struct cx88_board cx88_boards[] = { .gpio3 = 0x00100000, }}, }, + [CX88_BOARD_ATI_HDTVWONDER] = { + .name = "ATI HDTV Wonder", + .tuner_type = TUNER_PHILIPS_TUV1236D, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000ff7, + .gpio1 = 0x000000ff, + .gpio2 = 0x00000001, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000ffe, + .gpio1 = 0x000000ff, + .gpio2 = 0x00000001, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000ffe, + .gpio1 = 0x000000ff, + .gpio2 = 0x00000001, + .gpio3 = 0x00000000, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -958,6 +987,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1461, .subdevice = 0x8011, .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, + },{ + .subvendor = PCI_VENDOR_ID_ATI, + .subdevice = 0xa101, + .card = CX88_BOARD_ATI_HDTVWONDER, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1159,6 +1192,22 @@ void cx88_card_setup(struct cx88_core *core) cx_clear(MO_GP0_IO, 0x00000007); cx_set(MO_GP2_IO, 0x00000101); break; + case CX88_BOARD_ATI_HDTVWONDER: + if (0 == core->i2c_rc) { + /* enable tuner */ + int i; + u8 buffer[12]; + core->i2c_client.addr = 0x0a; + buffer[0] = 0x10; buffer[1] = 0x12; buffer[2] = 0x13; buffer[3] = 0x04; + buffer[4] = 0x16; buffer[5] = 0x00; buffer[6] = 0x14; buffer[7] = 0x04; + buffer[8] = 0x14; buffer[9] = 0x00; buffer[10] = 0x17; buffer[11] = 0x00; + + for (i = 0; i < 6; i++) + if (2 != i2c_master_send(&core->i2c_client,&buffer[i*2],2)) + printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n", + core->name, i); + } + break; } if (cx88_boards[core->board].radio.type == CX88_RADIO) core->has_radio = 1; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 9b629221e799..cc2197a85d01 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -176,6 +176,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 #define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32 #define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33 +#define CX88_BOARD_ATI_HDTVWONDER 34 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index b75ad2d4488a..e67d9e77c755 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -233,7 +233,7 @@ static struct tunertype tuners[] = { { "Ymec TVision TVF-5533MF", Philips, NTSC, 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, - /* 60-67 */ + /* 60-68 */ { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, @@ -250,6 +250,8 @@ static struct tunertype tuners[] = { 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, { "Philips TD1316 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, + { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, + 16*157.25,16*454.00,0x01,0x02,0x03,0xce,732 }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); @@ -375,6 +377,17 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* Set the charge pump for fast tuning */ tun->config |= TUNER_CHARGE_PUMP; break; + + case TUNER_PHILIPS_TUV1236D: + /* 0x40 -> ATSC antenna input 1 */ + /* 0x48 -> ATSC antenna input 2 */ + /* 0x00 -> NTSC antenna input 1 */ + /* 0x08 -> NTSC antenna input 2 */ + config &= ~0x40; + if (t->std & V4L2_STD_ATSC) + config |= 0x40; + /* FIXME: input */ + break; } /* diff --git a/include/media/tuner.h b/include/media/tuner.h index 97e16bddf651..7cc74b1bb6ea 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -112,6 +112,8 @@ #define TUNER_LG_NTSC_TALN_MINI 66 #define TUNER_PHILIPS_TD1316 67 +#define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ + #define NOTUNER 0 #define PAL 1 /* PAL_BG */ #define PAL_I 2 -- cgit v1.2.3 From 40c717ff48b2c91091a69de0e28c02a43e9b0c7c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:21 -0800 Subject: [PATCH] v4l: 763: include newer i2c id at linux include media id h - Include newer I2C ID at ../linux/include/media/id.h: Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/media/id.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include') diff --git a/include/media/id.h b/include/media/id.h index 6d02c94cdc0d..4f58d73e7029 100644 --- a/include/media/id.h +++ b/include/media/id.h @@ -33,3 +33,18 @@ #ifndef I2C_DRIVERID_SAA6752HS # define I2C_DRIVERID_SAA6752HS I2C_DRIVERID_EXP0+8 #endif +#ifndef I2C_DRIVERID_WM8775 +#define I2C_DRIVERID_WM8775 I2C_DRIVERID_EXP0+9 +#endif +#ifndef I2C_DRIVERID_CS53L32A +#define I2C_DRIVERID_CS53L32A I2C_DRIVERID_EXP0+10 +#endif +#ifndef I2C_DRIVERID_CX25840 +#define I2C_DRIVERID_CX25840 I2C_DRIVERID_EXP0+11 +#endif +#ifndef I2C_DRIVERID_SAA7115 +#define I2C_DRIVERID_SAA7115 I2C_DRIVERID_EXP0+12 +#endif +#ifndef I2C_DRIVERID_SAA7127 +#define I2C_DRIVERID_SAA7127 I2C_DRIVERID_EXP0+13 +#endif -- cgit v1.2.3 From d5e5265315770bda46c50ecaa64e2b9790f2064c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:32 -0800 Subject: [PATCH] v4l: 784: several improvement on i2c ir handling for em2820 - Several Improvement on I2C IR handling for em2820: - moved Pinnacle IR table (ir_codes_em2820) to em2820-input.c - IR struct renamed and moved to a header file. - New file to handle em2820-specific IR. - Some cleanups. - attach now detects I2C IR and calls em2820-specific IR code - IR compat code moved to compat.h - New header with struct IR_i2c there, to allow it to be used by board-specific input handlers. - Some improvements at em28xx board detection: - Board detection message improved to show interface and class. - Now it doesn't touch audio interfaces. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 3 +- drivers/media/video/em28xx/em28xx-i2c.c | 43 +++--- drivers/media/video/em28xx/em28xx-input.c | 150 +++++++++++++++++++ drivers/media/video/em28xx/em28xx-video.c | 15 +- drivers/media/video/em28xx/em28xx.h | 20 ++- drivers/media/video/ir-kbd-i2c.c | 238 +++++++++++------------------- include/media/ir-common.h | 6 +- include/media/ir-kbd-i2c.h | 22 +++ 8 files changed, 307 insertions(+), 190 deletions(-) create mode 100644 drivers/media/video/em28xx/em28xx-input.c create mode 100644 include/media/ir-kbd-i2c.h (limited to 'include') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 91c70ebd0ea4..919520f89975 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -143,7 +143,7 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, .has_tuner = 1, - .decoder = EM2820_SAA7114, + .decoder = EM2820_SAA7114, .input = {{ .type = EM2820_VMUX_TELEVISION, .vmux = 2, @@ -250,6 +250,7 @@ void em2820_card_setup(struct em2820 *dev) struct tveeprom tv; #ifdef CONFIG_MODULES request_module("tveeprom"); + request_module("ir-kbd-i2c"); #endif /* Call first TVeeprom */ diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index a7b6f678f979..f6bfc038777e 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -26,10 +26,10 @@ #include #include #include -#include #include #include "em2820.h" +#include /* ----------------------------------------------------------- */ @@ -41,14 +41,11 @@ static unsigned int i2c_debug = 0; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -#define dprintk(fmt, args...) if (i2c_debug) do {\ - printk(KERN_DEBUG "%s: %s: " fmt "\n",\ - dev->name, __FUNCTION__ , ##args); } while (0) -#define dprintk1(fmt, args...) if (i2c_debug) do{ \ - printk(KERN_DEBUG "%s: %s: " fmt, \ - dev->name, __FUNCTION__ , ##args); } while (0) -#define dprintk2(fmt, args...) if (i2c_debug) do {\ +#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\ printk(fmt , ##args); } while (0) +#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ + printk(KERN_DEBUG "%s at %s: " fmt, \ + dev->name, __FUNCTION__ , ##args); } while (0) /* * em2800_i2c_send_max4() @@ -238,7 +235,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, return 0; for (i = 0; i < num; i++) { addr = msgs[i].addr << 1; - dprintk1("%s %s addr=%x len=%d:", + dprintk2(2,"%s %s addr=%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (!msgs[i].len) { /* no len: check only for device presence */ @@ -247,7 +244,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, else rc = em2820_i2c_check_for_device(dev, addr); if (rc < 0) { - dprintk2(" no device\n"); + dprintk2(2," no device\n"); return rc; } @@ -261,14 +258,14 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, rc = em2820_i2c_recv_bytes(dev, addr, msgs[i].buf, msgs[i].len); - if (i2c_debug) { + if (i2c_debug>=2) { for (byte = 0; byte < msgs[i].len; byte++) { printk(" %02x", msgs[i].buf[byte]); } } } else { /* write bytes */ - if (i2c_debug) { + if (i2c_debug>=2) { for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } @@ -284,13 +281,13 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, if (rc < 0) goto err; } - if (i2c_debug) + if (i2c_debug>=2) printk("\n"); } return num; err: - dprintk2(" ERROR: %i\n", rc); + dprintk2(2," ERROR: %i\n", rc); return rc; } @@ -436,26 +433,34 @@ static int attach_inform(struct i2c_client *client) { struct em2820 *dev = client->adapter->algo_data; - dprintk("address %x", client->addr << 1); switch (client->addr << 1) { case 0x86: em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); break; case 0x4a: - dprintk1("attach_inform: saa7113 detected.\n"); + dprintk1(1,"attach_inform: saa7113 detected.\n"); break; case 0xa0: - dprintk1("attach_inform: eeprom detected.\n"); + dprintk1(1,"attach_inform: eeprom detected.\n"); + break; + case 0x60: + case 0x8e: + { + struct IR_i2c *ir = i2c_get_clientdata(client); + dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys); + em2820_set_ir(dev,ir); break; + } case 0x80: case 0x88: - dprintk1("attach_inform: msp34xx detected.\n"); + dprintk1(1,"attach_inform: msp34xx detected.\n"); break; case 0xb8: case 0xba: - dprintk1("attach_inform: tvp5150 detected.\n"); + dprintk1(1,"attach_inform: tvp5150 detected.\n"); break; default: + dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); dev->tuner_addr = client->addr; em2820_set_tuner(-1, client); } diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c new file mode 100644 index 000000000000..d6b3e15a0350 --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -0,0 +1,150 @@ +/* + * + * handle saa7134 IR remotes via linux kernel input layer. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "em2820.h" + +static unsigned int disable_ir = 0; +module_param(disable_ir, int, 0444); +MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); + +static unsigned int ir_debug = 0; +module_param(ir_debug, int, 0644); +MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); + +#define dprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) + +/* ---------------------------------------------------------------------- */ + +static IR_KEYTAB_TYPE ir_codes_em_pinnacle[IR_KEYTAB_SIZE] = { + [ 0 ] = KEY_CHANNEL, + [ 1 ] = KEY_SELECT, + [ 2 ] = KEY_MUTE, + [ 3 ] = KEY_POWER, + [ 4 ] = KEY_KP1, + [ 5 ] = KEY_KP2, + [ 6 ] = KEY_KP3, + [ 7 ] = KEY_CHANNELUP, + [ 8 ] = KEY_KP4, + [ 9 ] = KEY_KP5, + [ 10 ] = KEY_KP6, + + [ 11 ] = KEY_CHANNELDOWN, + [ 12 ] = KEY_KP7, + [ 13 ] = KEY_KP8, + [ 14 ] = KEY_KP9, + [ 15 ] = KEY_VOLUMEUP, + [ 16 ] = KEY_KP0, + [ 17 ] = KEY_MENU, + [ 18 ] = KEY_PRINT, + + [ 19 ] = KEY_VOLUMEDOWN, + [ 21 ] = KEY_PAUSE, + [ 23 ] = KEY_RECORD, + [ 24 ] = KEY_REWIND, + [ 25 ] = KEY_PLAY, + [ 27 ] = KEY_BACKSPACE, + [ 29 ] = KEY_STOP, + [ 31 ] = KEY_ZOOM, +}; + +/* ----------------------------------------------------------------------- */ + +static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char buf[2]; + unsigned char code; + + /* poll IR chip */ + if (2 != i2c_master_recv(&ir->c,buf,2)) + return -EIO; + + /* Does eliminate repeated parity code */ + if (buf[1]==0xff) + return 0; + + /* avoid fast reapeating */ + if (buf[1]==ir->old) + return 0; + ir->old=buf[1]; + + /* Rearranges bits to the right order */ + code= ((buf[0]&0x01)<<5) | /* 0010 0000 */ + ((buf[0]&0x02)<<3) | /* 0001 0000 */ + ((buf[0]&0x04)<<1) | /* 0000 1000 */ + ((buf[0]&0x08)>>1) | /* 0000 0100 */ + ((buf[0]&0x10)>>3) | /* 0000 0010 */ + ((buf[0]&0x20)>>5); /* 0000 0001 */ + + dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]); + + /* return key */ + *ir_key = code; + *ir_raw = code; + return 1; +} + +/* ----------------------------------------------------------------------- */ +void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) +{ + if (disable_ir) + return ; + + /* detect & configure */ + switch (dev->model) { + case (EM2800_BOARD_UNKNOWN): + break; + case (EM2820_BOARD_UNKNOWN): + break; + case (EM2820_BOARD_TERRATEC_CINERGY_250): + break; + case (EM2820_BOARD_PINNACLE_USB_2): + ir->ir_codes = ir_codes_em_pinnacle; + break; + case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): + ir->ir_codes = ir_codes_hauppauge_new; + ir->get_key = get_key_em_haup; + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2840 Hauppage)"); + break; + case (EM2820_BOARD_MSI_VOX_USB_2): + break; + case (EM2800_BOARD_TERRATEC_CINERGY_200): + break; + case (EM2800_BOARD_LEADTEK_WINFAST_USBII): + break; + case (EM2800_BOARD_KWORLD_USB2800): + break; + } +} + +/* ---------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d3a959b9ee64..f3fc44b352b4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,10 +28,10 @@ #include #include #include -#include #include #include "em2820.h" +#include #define DRIVER_AUTHOR "Markus Rechberger , " \ "Ludovico Cavedon , " \ @@ -1699,15 +1699,22 @@ static int em2820_usb_probe(struct usb_interface *interface, struct usb_device *udev; struct em2820 *dev = NULL; int retval = -ENODEV; - int model,i,nr; + int model,i,nr,ifnum; udev = usb_get_dev(interface_to_usbdev(interface)); - endpoint = &interface->cur_altsetting->endpoint[1].desc; + ifnum = interface->altsetting[0].desc.bInterfaceNumber; + + em2820_err(DRIVER_NAME " new device (%04x:%04x): interface %i, class %i\n", + udev->descriptor.idVendor,udev->descriptor.idProduct, + ifnum, + interface->altsetting[0].desc.bInterfaceClass); /* Don't register audio interfaces */ - if (interface->altsetting[1].desc.bInterfaceClass == USB_CLASS_AUDIO) + if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) return -ENODEV; + endpoint = &interface->cur_altsetting->endpoint[1].desc; + /* check if the the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 4115938a1731..31b23f0db051 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -27,6 +27,7 @@ #include #include +#include /* Boards supported by driver */ @@ -53,19 +54,12 @@ /* number of buffers for isoc transfers */ #define EM2820_NUM_BUFS 5 -/* number of packets for each buffer */ -// windows requests only 40 packets .. so we better do the same -// this is what I found out for all alternate numbers there! - +/* number of packets for each buffer + windows requests only 40 packets .. so we better do the same + this is what I found out for all alternate numbers there! + */ #define EM2820_NUM_PACKETS 40 -/* packet size for each packet */ -/* no longer needed: read from endpoint descriptor */ -//#define EM2820_MAX_PACKET_SIZE 3072 //7 -//#define EM2820_MAX_PACKET_SIZE 2892 //6 -//#define EM2820_MAX_PACKET_SIZE 2580 //5 -//#define EM2820_MAX_PACKET_SIZE 1448 //2 - /* default alternate; 0 means choose the best */ #define EM2820_PINOUT 0 #define EM2820_MAX_ALT 7 @@ -292,6 +286,10 @@ void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg); int em2820_i2c_register(struct em2820 *dev); int em2820_i2c_unregister(struct em2820 *dev); +/* Provided by em2820-input.c */ + +void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir); + /* Provided by em2820-core.c */ void em2820_print_ioctl(char *name, unsigned int cmd); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index aec710f4effc..8cc3f8ab2f3a 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -41,101 +41,71 @@ #include #include #include - -static IR_KEYTAB_TYPE ir_codes_em2820[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, - [ 0x1b ] = KEY_FORWARD, - [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, -}; +#include /* Mark Phalan */ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_KP0, - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - [ 0x12 ] = KEY_POWER, - [ 0x10 ] = KEY_MUTE, - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x0e ] = KEY_PAGEUP, - [ 0x1d ] = KEY_PAGEDOWN, - [ 0x13 ] = KEY_SOUND, - - [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 0x16 ] = KEY_SUBTITLE, /* CC */ - [ 0x0d ] = KEY_TEXT, /* TTX */ - [ 0x0b ] = KEY_TV, /* AIR/CBL */ - [ 0x11 ] = KEY_PC, /* PC/TV */ - [ 0x17 ] = KEY_OK, /* CH RTN */ - [ 0x19 ] = KEY_MODE, /* FUNC */ - [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ + [ 0 ] = KEY_KP0, + [ 1 ] = KEY_KP1, + [ 2 ] = KEY_KP2, + [ 3 ] = KEY_KP3, + [ 4 ] = KEY_KP4, + [ 5 ] = KEY_KP5, + [ 6 ] = KEY_KP6, + [ 7 ] = KEY_KP7, + [ 8 ] = KEY_KP8, + [ 9 ] = KEY_KP9, + + [ 18 ] = KEY_POWER, + [ 16 ] = KEY_MUTE, + [ 31 ] = KEY_VOLUMEDOWN, + [ 27 ] = KEY_VOLUMEUP, + [ 26 ] = KEY_CHANNELUP, + [ 30 ] = KEY_CHANNELDOWN, + [ 14 ] = KEY_PAGEUP, + [ 29 ] = KEY_PAGEDOWN, + [ 19 ] = KEY_SOUND, + + [ 24 ] = KEY_KPPLUSMINUS, /* CH +/- */ + [ 22 ] = KEY_SUBTITLE, /* CC */ + [ 13 ] = KEY_TEXT, /* TTX */ + [ 11 ] = KEY_TV, /* AIR/CBL */ + [ 17 ] = KEY_PC, /* PC/TV */ + [ 23 ] = KEY_OK, /* CH RTN */ + [ 25 ] = KEY_MODE, /* FUNC */ + [ 12 ] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [ 0x0f ] = KEY_SELECT, /* SOURCE */ - [ 0x0a ] = KEY_KPPLUS, /* +100 */ - [ 0x14 ] = KEY_KPEQUAL, /* SYNC */ - [ 0x1c ] = KEY_MEDIA, /* PC/TV */ + [ 15 ] = KEY_SELECT, /* SOURCE */ + [ 10 ] = KEY_KPPLUS, /* +100 */ + [ 20 ] = KEY_KPEQUAL, /* SYNC */ + [ 28 ] = KEY_MEDIA, /* PC/TV */ }; static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x03 ] = KEY_POWER, + [ 0x3 ] = KEY_POWER, [ 0x6f ] = KEY_MUTE, [ 0x10 ] = KEY_BACKSPACE, /* Recall */ [ 0x11 ] = KEY_KP0, - [ 0x04 ] = KEY_KP1, - [ 0x05 ] = KEY_KP2, - [ 0x06 ] = KEY_KP3, - [ 0x08 ] = KEY_KP4, - [ 0x09 ] = KEY_KP5, - [ 0x0a ] = KEY_KP6, - [ 0x0c ] = KEY_KP7, - [ 0x0d ] = KEY_KP8, - [ 0x0e ] = KEY_KP9, + [ 0x4 ] = KEY_KP1, + [ 0x5 ] = KEY_KP2, + [ 0x6 ] = KEY_KP3, + [ 0x8 ] = KEY_KP4, + [ 0x9 ] = KEY_KP5, + [ 0xa ] = KEY_KP6, + [ 0xc ] = KEY_KP7, + [ 0xd ] = KEY_KP8, + [ 0xe ] = KEY_KP9, [ 0x12 ] = KEY_KPDOT, /* 100+ */ - [ 0x07 ] = KEY_VOLUMEUP, - [ 0x0b ] = KEY_VOLUMEDOWN, + [ 0x7 ] = KEY_VOLUMEUP, + [ 0xb ] = KEY_VOLUMEDOWN, [ 0x1a ] = KEY_KPPLUS, [ 0x18 ] = KEY_KPMINUS, [ 0x15 ] = KEY_UP, [ 0x1d ] = KEY_DOWN, - [ 0x0f ] = KEY_CHANNELUP, + [ 0xf ] = KEY_CHANNELUP, [ 0x13 ] = KEY_CHANNELDOWN, [ 0x48 ] = KEY_ZOOM, @@ -152,17 +122,6 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { }; -struct IR { - struct i2c_client c; - struct input_dev *input; - struct ir_input_state ir; - - struct work_struct work; - struct timer_list timer; - char phys[32]; - int (*get_key)(struct IR*, u32*, u32*); -}; - /* ----------------------------------------------------------------------- */ /* insmod parameters */ @@ -173,12 +132,9 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */ #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) -#define IR_PINNACLE_REMOTE 0x01 -#define IR_TERRATEC_REMOTE 0x02 - /* ----------------------------------------------------------------------- */ -static int get_key_haup(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[3]; int start, toggle, dev, code; @@ -205,7 +161,7 @@ static int get_key_haup(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_pixelview(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -219,7 +175,7 @@ static int get_key_pixelview(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -239,7 +195,7 @@ static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -267,7 +223,7 @@ static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -289,10 +245,9 @@ static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw) *ir_raw = b; return 1; } - /* ----------------------------------------------------------------------- */ -static void ir_key_poll(struct IR *ir) +static void ir_key_poll(struct IR_i2c *ir) { static u32 ir_key, ir_raw; int rc; @@ -313,13 +268,13 @@ static void ir_key_poll(struct IR *ir) static void ir_timer(unsigned long data) { - struct IR *ir = (struct IR*)data; + struct IR_i2c *ir = (struct IR_i2c*)data; schedule_work(&ir->work); } static void ir_work(void *data) { - struct IR *ir = data; + struct IR_i2c *ir = data; ir_key_poll(ir); mod_timer(&ir->timer, jiffies+HZ/10); } @@ -351,10 +306,10 @@ static int ir_attach(struct i2c_adapter *adap, int addr, IR_KEYTAB_TYPE *ir_codes = NULL; char *name; int ir_type; - struct IR *ir; + struct IR_i2c *ir; struct input_dev *input_dev; - ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); input_dev = input_allocate_device(); if (!ir || !input_dev) { kfree(ir); @@ -390,36 +345,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_codes = ir_codes_rc5_tv; break; case 0x30: - switch(kind){ - case IR_TERRATEC_REMOTE: - name = "Terratec IR"; - ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_em2820; - break; - default: - name = "KNC One"; - ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_empty; - } + name = "KNC One"; + ir->get_key = get_key_knc1; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_empty; break; - case 0x47: case 0x7a: - switch(kind){ - case IR_PINNACLE_REMOTE: - name = "Pinnacle IR Remote"; - ir->get_key = get_key_purpletv; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_em2820; - break; - default: - name = "Purple TV"; - ir->get_key = get_key_purpletv; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_purpletv; - } + name = "Purple TV"; + ir->get_key = get_key_purpletv; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_purpletv; break; + default: /* shouldn't happen */ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); @@ -427,12 +364,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr, return -1; } - /* register i2c device */ - i2c_attach_client(&ir->c); + /* Sets name and its physical addr */ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", ir->c.adapter->dev.bus_id, ir->c.dev.bus_id); + ir->ir_codes=ir_codes; + + /* register i2c device + * At device register, IR codes may be changed to be + * board dependent. + */ + i2c_attach_client(&ir->c); /* init + register input device */ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); @@ -440,6 +383,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, input_dev->name = ir->c.name; input_dev->phys = ir->phys; + /* register event device */ input_register_device(ir->input); /* start polling via eventd */ @@ -454,7 +398,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, static int ir_detach(struct i2c_client *client) { - struct IR *ir = i2c_get_clientdata(client); + struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ del_timer(&ir->timer); @@ -483,11 +427,9 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, -1 }; - static const int probe_em2820[] = { 0x47, 0x30, -1 }; + static const int probe_em2820[] = { 0x30, 0x47, -1 }; const int *probe = NULL; - int attached = 0; - - struct i2c_client c; unsigned char buf; int i,rc; + struct i2c_client c; char buf; int i,rc; switch (adap->id) { case I2C_HW_B_BT848: @@ -505,27 +447,15 @@ static int ir_probe(struct i2c_adapter *adap) memset(&c,0,sizeof(c)); c.adapter = adap; - for (i = 0; -1 != probe[i] && attached != 1; i++) { + for (i = 0; -1 != probe[i]; i++) { c.addr = probe[i]; - rc = i2c_master_recv(&c,&buf,1); + rc = i2c_master_recv(&c,&buf,0); dprintk(1,"probe 0x%02x @ %s: %s\n", probe[i], adap->name, - (1 == rc) ? "yes" : "no"); - switch(adap->id){ - case I2C_HW_B_BT848: - case I2C_HW_SAA7134: - if (1 == rc) { - ir_attach(adap,probe[i],0,0); - attached=1; - break; - } - case I2C_HW_B_EM2820: - /* windows logs are needed for fixing the pinnacle device */ - if (1 == rc && 0xff == buf){ - ir_attach(adap,probe[i],0,IR_TERRATEC_REMOTE); - attached=1; - } - break; + (0 == rc) ? "yes" : "no"); + if (0 == rc) { + ir_attach(adap,probe[i],0,0); + break; } } return 0; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 01b56822df4d..0f1ba95ec8d6 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -20,8 +20,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#ifndef _IR_COMMON +#define _IR_COMMON +#include #define IR_TYPE_RC5 1 #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ @@ -61,6 +63,8 @@ int ir_dump_samples(u32 *samples, int count); int ir_decode_biphase(u32 *samples, int count, int low, int high); int ir_decode_pulsedistance(u32 *samples, int count, int low, int high); +#endif + /* * Local variables: * c-basic-offset: 8 diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h new file mode 100644 index 000000000000..00fa57eb9fde --- /dev/null +++ b/include/media/ir-kbd-i2c.h @@ -0,0 +1,22 @@ +#ifndef _IR_I2C +#define _IR_I2C + +#include + +struct IR_i2c; + +struct IR_i2c { + IR_KEYTAB_TYPE *ir_codes; + struct i2c_client c; + struct input_dev *input; + struct ir_input_state ir; + + /* Used to avoid fast repeating */ + unsigned char old; + + struct work_struct work; + struct timer_list timer; + char phys[32]; + int (*get_key)(struct IR_i2c*, u32*, u32*); +}; +#endif -- cgit v1.2.3 From 3ae1adc6ed93d55a27523f395284940fbe056401 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:39 -0800 Subject: [PATCH] v4l: 795: new config option for tda9887 to specifically set intercarrier - New config option for tda9887 to specifically set intercarrier Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/tda9887.c | 2 ++ include/media/tuner.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6a85ba111fb1..cf17da836914 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -206,7 +206,7 @@ struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 3a7babef06f4..796110d4ff72 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -464,6 +464,8 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) break; } } + if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) + buf[1] &= ~cQSS; return 0; } diff --git a/include/media/tuner.h b/include/media/tuner.h index 7cc74b1bb6ea..81025323267f 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -148,6 +148,7 @@ # define TDA9887_INTERCARRIER (1<<4) # define TDA9887_PORT1_ACTIVE (1<<5) # define TDA9887_PORT2_ACTIVE (1<<6) +# define TDA9887_INTERCARRIER_NTSC (1<<7) /* config options */ # define TDA9887_DEEMPHASIS_MASK (3<<16) # define TDA9887_DEEMPHASIS_NONE (1<<16) -- cgit v1.2.3 From 299392bf2040fc53ebfc94363ac0abdd0f0bf619 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:42 -0800 Subject: [PATCH] v4l: 798: this patch adds the vidioc log status to videodev2 h and adds - This patch adds the VIDIOC_LOG_STATUS to videodev2.h and adds LOG_STATUS support to tda9887.c and bttv-driver.c. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-driver.c | 6 ++++++ drivers/media/video/tda9887.c | 29 +++++++++++++++++------------ include/linux/videodev2.h | 1 + 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 058b923b4b13..f8307407e320 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1851,6 +1851,11 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) up(&btv->lock); return 0; } + case VIDIOC_LOG_STATUS: + { + bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, 0); + return 0; + } default: return -ENOIOCTLCMD; @@ -2856,6 +2861,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_TUNER: case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: + case VIDIOC_LOG_STATUS: return bttv_common_ioctls(btv,cmd,arg); default: diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 796110d4ff72..6d2914f738f2 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -60,6 +60,7 @@ struct tda9887 { unsigned int pinnacle_id; unsigned int using_v4l2; unsigned int radio_mode; + unsigned char data[4]; }; struct tvnorm { @@ -575,32 +576,31 @@ static int tda9887_status(struct tda9887 *t) static int tda9887_configure(struct tda9887 *t) { - unsigned char buf[4]; int rc; - memset(buf,0,sizeof(buf)); - tda9887_set_tvnorm(t,buf); + memset(t->data,0,sizeof(t->data)); + tda9887_set_tvnorm(t,t->data); - buf[1] |= cOutputPort1Inactive; - buf[1] |= cOutputPort2Inactive; + t->data[1] |= cOutputPort1Inactive; + t->data[1] |= cOutputPort2Inactive; if (UNSET != t->pinnacle_id) { - tda9887_set_pinnacle(t,buf); + tda9887_set_pinnacle(t,t->data); } - tda9887_set_config(t,buf); - tda9887_set_insmod(t,buf); + tda9887_set_config(t,t->data); + tda9887_set_insmod(t,t->data); if (t->mode == T_STANDBY) { - buf[1] |= cForcedMuteAudioON; + t->data[1] |= cForcedMuteAudioON; } tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - buf[1],buf[2],buf[3]); + t->data[1],t->data[2],t->data[3]); if (debug > 1) - dump_write_message(t, buf); + dump_write_message(t, t->data); - if (4 != (rc = i2c_master_send(&t->client,buf,4))) + if (4 != (rc = i2c_master_send(&t->client,t->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { @@ -785,6 +785,11 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) } break; } + case VIDIOC_LOG_STATUS: + { + tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]); + break; + } default: /* nothing */ break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 89a055761bed..27979003db44 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -981,6 +981,7 @@ struct v4l2_streamparm #if 1 #define VIDIOC_G_SLICED_VBI_CAP _IOR ('V', 69, struct v4l2_sliced_vbi_cap) #endif +#define VIDIOC_LOG_STATUS _IO ('V', 70) /* for compatibility, will go away some day */ #define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) -- cgit v1.2.3 From 4ac97914c6c35f6bf132071c718e034d0846b9f5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:43 -0800 Subject: [PATCH] v4l: 800: whitespace cleanups - Whitespace Cleanups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/README.cx88 | 6 +- Documentation/video4linux/bttv/Cards | 18 +- Documentation/video4linux/bttv/README | 6 +- Documentation/video4linux/bttv/Sound-FAQ | 6 +- Documentation/video4linux/lifeview.txt | 58 +-- drivers/media/common/ir-common.c | 4 +- drivers/media/video/bt832.c | 88 ++--- drivers/media/video/bt832.h | 4 +- drivers/media/video/bttv-cards.c | 260 ++++++------- drivers/media/video/bttv-driver.c | 342 ++++++++--------- drivers/media/video/bttv-gpio.c | 2 +- drivers/media/video/bttv-i2c.c | 42 +-- drivers/media/video/bttv-if.c | 4 +- drivers/media/video/bttv-risc.c | 110 +++--- drivers/media/video/bttv.h | 20 +- drivers/media/video/bttvp.h | 14 +- drivers/media/video/cx88/cx88-blackbird.c | 40 +- drivers/media/video/cx88/cx88-cards.c | 340 ++++++++--------- drivers/media/video/cx88/cx88-core.c | 40 +- drivers/media/video/cx88/cx88-dvb.c | 16 +- drivers/media/video/cx88/cx88-i2c.c | 22 +- drivers/media/video/cx88/cx88-input.c | 2 +- drivers/media/video/cx88/cx88-mpeg.c | 18 +- drivers/media/video/cx88/cx88-reg.h | 12 +- drivers/media/video/cx88/cx88-video.c | 22 +- drivers/media/video/cx88/cx88.h | 4 +- drivers/media/video/em28xx/em28xx-cards.c | 4 +- drivers/media/video/em28xx/em28xx-core.c | 28 +- drivers/media/video/em28xx/em28xx-i2c.c | 4 +- drivers/media/video/em28xx/em28xx-input.c | 52 +-- drivers/media/video/em28xx/em28xx-video.c | 10 +- drivers/media/video/em28xx/em28xx.h | 12 +- drivers/media/video/ir-kbd-gpio.c | 4 +- drivers/media/video/ir-kbd-i2c.c | 22 +- drivers/media/video/msp3400.c | 62 ++-- drivers/media/video/mt20xx.c | 204 +++++------ drivers/media/video/saa711x.c | 4 +- drivers/media/video/saa7134/saa6752hs.c | 62 ++-- drivers/media/video/saa7134/saa7134-alsa.c | 504 +++++++++++++------------- drivers/media/video/saa7134/saa7134-cards.c | 314 ++++++++-------- drivers/media/video/saa7134/saa7134-core.c | 38 +- drivers/media/video/saa7134/saa7134-dvb.c | 4 +- drivers/media/video/saa7134/saa7134-empress.c | 6 +- drivers/media/video/saa7134/saa7134-i2c.c | 14 +- drivers/media/video/saa7134/saa7134-input.c | 100 ++--- drivers/media/video/saa7134/saa7134-oss.c | 68 ++-- drivers/media/video/saa7134/saa7134-reg.h | 18 +- drivers/media/video/saa7134/saa7134-ts.c | 4 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 12 +- drivers/media/video/saa7134/saa7134-video.c | 106 +++--- drivers/media/video/saa7134/saa7134.h | 12 +- drivers/media/video/tda7432.c | 16 +- drivers/media/video/tda8290.c | 2 +- drivers/media/video/tda9875.c | 56 +-- drivers/media/video/tda9887.c | 36 +- drivers/media/video/tea5767.c | 8 +- drivers/media/video/tuner-core.c | 30 +- drivers/media/video/tuner-simple.c | 106 +++--- drivers/media/video/tvaudio.c | 20 +- drivers/media/video/tveeprom.c | 20 +- drivers/media/video/tvmixer.c | 54 +-- drivers/media/video/v4l1-compat.c | 2 +- drivers/media/video/video-buf.c | 18 +- drivers/media/video/wm8775.c | 4 +- include/linux/videodev.h | 6 +- include/linux/videodev2.h | 118 +++--- include/media/audiochip.h | 14 +- include/media/tuner.h | 8 +- include/media/video-buf.h | 2 +- 69 files changed, 1844 insertions(+), 1844 deletions(-) (limited to 'include') diff --git a/Documentation/video4linux/README.cx88 b/Documentation/video4linux/README.cx88 index 0b93455bbc17..06a33a4f52fd 100644 --- a/Documentation/video4linux/README.cx88 +++ b/Documentation/video4linux/README.cx88 @@ -17,9 +17,9 @@ audio - The chip specs for the on-chip TV sound decoder are next to useless :-/ - Neverless the builtin TV sound decoder starts working now, - at least for PAL-BG. Other TV norms need other code ... - FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE - USING. + at least for PAL-BG. Other TV norms need other code ... + FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE + USING. - Most tuner chips do provide mono sound, which may or may not be useable depending on the board design. With the Hauppauge cards it works, so there is mono sound available as fallback. diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards index 8f1941ede4da..d3389655ad96 100644 --- a/Documentation/video4linux/bttv/Cards +++ b/Documentation/video4linux/bttv/Cards @@ -149,11 +149,11 @@ Lifeview Flyvideo Series: 2) There is a print on the PCB: LR25 = Flyvideo (Zoran ZR36120, SAA7110A) LR26 Rev.N = Flyvideo II (Bt848) - Rev.O = Flyvideo II (Bt878) + Rev.O = Flyvideo II (Bt878) LR37 Rev.C = Flyvideo EZ (Capture only, ZR36120 + SAA7110) LR38 Rev.A1= Flyvideo II EZ (Bt848 capture only) LR50 Rev.Q = Flyvideo 98 (w/eeprom and PCI subsystem ID) - Rev.W = Flyvideo 98 (no eeprom) + Rev.W = Flyvideo 98 (no eeprom) LR51 Rev.E = Flyvideo 98 EZ (capture only) LR90 = Flyvideo 2000 (Bt878) Flyvideo 2000S (Bt878) w/Stereo TV (Package incl. LR91 daughterboard) @@ -163,7 +163,7 @@ Lifeview Flyvideo Series: LR136 = Flyvideo 2100/3100 (Low profile, SAA7130/SAA7134) LR137 = Flyvideo DV2000/DV3000 (SAA7130/SAA7134 + IEEE1394) LR138 Rev.C= Flyvideo 2000 (SAA7130) - or Flyvideo 3000 (SAA7134) w/Stereo TV + or Flyvideo 3000 (SAA7134) w/Stereo TV These exist in variations w/FM and w/Remote sometimes denoted by suffixes "FM" and "R". 3) You have a laptop (miniPCI card): @@ -197,7 +197,7 @@ Typhoon TV card series: 50680 "TV Tuner Pal BG" (blue package)= Pixelview PV-BT878P+ (Rev 9B) 50681 "TV Tuner PCI Pal I" (variant of 50680) 50682 "TView TV/FM Tuner Pal BG" = Flyvideo 98FM (LR50 Rev.Q) - Note: The package has a picture of CPH05x (which would be a real TView) + Note: The package has a picture of CPH05x (which would be a real TView) 50683 "TV Tuner PCI SECAM" (variant of 50680) 50684 "TV Tuner Pal BG" = Pixelview 878TV(Rev.3D) 50686 "TV Tuner" = KNC1 TV Station @@ -418,9 +418,9 @@ Lifetec/Medion/Tevion/Aldi -------------------------- LT9306/MD9306 = CPH061 LT9415/MD9415 = LR90 Rev.F or Rev.G - MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) - MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) - MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) + MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) + MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) + MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) Modular Technologies (www.modulartech.com) UK --------------------------------------------- @@ -453,10 +453,10 @@ Technisat Discos ADR PC-Karte ISA (no TV!) Discos ADR PC-Karte PCI (probably no TV?) Techni-PC-Sat (Sat. analog) - Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A) + Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A) Mediafocus I (zr36120/zr36125, drp3510, Sat. analog + ADR Radio) Mediafocus II (saa7146, Sat. analog) - SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A) + SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A) SkyStar 1 DVB (AV7110) = Technotrend Premium SkyStar 2 DVB (B2C2) (=Sky2PC) diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README index a72f4c94fb0b..7ca2154c2bf5 100644 --- a/Documentation/video4linux/bttv/README +++ b/Documentation/video4linux/bttv/README @@ -42,9 +42,9 @@ bttv uses the PCI Subsystem ID to autodetect the card type. lspci lists the Subsystem ID in the second line, looks like this: 00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02) - Subsystem: Hauppauge computer works Inc. WinTV/GO - Flags: bus master, medium devsel, latency 32, IRQ 5 - Memory at e2000000 (32-bit, prefetchable) [size=4K] + Subsystem: Hauppauge computer works Inc. WinTV/GO + Flags: bus master, medium devsel, latency 32, IRQ 5 + Memory at e2000000 (32-bit, prefetchable) [size=4K] only bt878-based cards can have a subsystem ID (which does not mean that every card really has one). bt848 cards can't have a Subsystem diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ index 5c9822492034..1e6328f91083 100644 --- a/Documentation/video4linux/bttv/Sound-FAQ +++ b/Documentation/video4linux/bttv/Sound-FAQ @@ -61,8 +61,8 @@ line for your board. The important fields are these two: struct tvcard { [ ... ] - u32 gpiomask; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ }; gpiomask specifies which pins are used to control the audio mux chip. @@ -126,7 +126,7 @@ muxsel - video mux, input->registervalue mapping pll - same as pll= insmod option tuner_type - same as tuner= insmod option *_modulename - hint whenever some card needs this or that audio - module loaded to work properly. + module loaded to work properly. has_radio - whenever this TV card has a radio tuner. no_msp34xx - "1" disables loading of msp3400.o module no_tda9875 - "1" disables loading of tda9875.o module diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt index b07ea79c2b7e..f66320bd7b67 100644 --- a/Documentation/video4linux/lifeview.txt +++ b/Documentation/video4linux/lifeview.txt @@ -10,33 +10,33 @@ bt878: ------------------------------------------------------------------------------ saa7134: - /* LifeView FlyTV Platinum FM (LR214WF) */ - /* "Peter Missel */ - .name = "LifeView FlyTV Platinum FM", - /* GP27 MDT2005 PB4 pin 10 */ - /* GP26 MDT2005 PB3 pin 9 */ - /* GP25 MDT2005 PB2 pin 8 */ - /* GP23 MDT2005 PB1 pin 7 */ - /* GP22 MDT2005 PB0 pin 6 */ - /* GP21 MDT2005 PB5 pin 11 */ - /* GP20 MDT2005 PB6 pin 12 */ - /* GP19 MDT2005 PB7 pin 13 */ - /* nc MDT2005 PA3 pin 2 */ - /* Remote MDT2005 PA2 pin 1 */ - /* GP18 MDT2005 PA1 pin 18 */ - /* nc MDT2005 PA0 pin 17 strap low */ + /* LifeView FlyTV Platinum FM (LR214WF) */ + /* "Peter Missel */ + .name = "LifeView FlyTV Platinum FM", + /* GP27 MDT2005 PB4 pin 10 */ + /* GP26 MDT2005 PB3 pin 9 */ + /* GP25 MDT2005 PB2 pin 8 */ + /* GP23 MDT2005 PB1 pin 7 */ + /* GP22 MDT2005 PB0 pin 6 */ + /* GP21 MDT2005 PB5 pin 11 */ + /* GP20 MDT2005 PB6 pin 12 */ + /* GP19 MDT2005 PB7 pin 13 */ + /* nc MDT2005 PA3 pin 2 */ + /* Remote MDT2005 PA2 pin 1 */ + /* GP18 MDT2005 PA1 pin 18 */ + /* nc MDT2005 PA0 pin 17 strap low */ - /* GP17 Strap "GP7"=High */ - /* GP16 Strap "GP6"=High - 0=Radio 1=TV - Drives SA630D ENCH1 and HEF4052 A1 pins - to do FM radio through SIF input */ - /* GP15 nc */ - /* GP14 nc */ - /* GP13 nc */ - /* GP12 Strap "GP5" = High */ - /* GP11 Strap "GP4" = High */ - /* GP10 Strap "GP3" = High */ - /* GP09 Strap "GP2" = Low */ - /* GP08 Strap "GP1" = Low */ - /* GP07.00 nc */ + /* GP17 Strap "GP7"=High */ + /* GP16 Strap "GP6"=High + 0=Radio 1=TV + Drives SA630D ENCH1 and HEF4052 A1 pins + to do FM radio through SIF input */ + /* GP15 nc */ + /* GP14 nc */ + /* GP13 nc */ + /* GP12 Strap "GP5" = High */ + /* GP11 Strap "GP4" = High */ + /* GP10 Strap "GP3" = High */ + /* GP09 Strap "GP2" = Low */ + /* GP08 Strap "GP1" = Low */ + /* GP07.00 nc */ diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 31fccb4f05d6..4b71fd6f7aed 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c @@ -116,7 +116,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [ 46 ] = KEY_BLUE, [ 24 ] = KEY_KPPLUS, /* fine tune + */ [ 25 ] = KEY_KPMINUS, /* fine tune - */ - [ 33 ] = KEY_KPDOT, + [ 33 ] = KEY_KPDOT, [ 19 ] = KEY_KPENTER, [ 34 ] = KEY_BACK, [ 35 ] = KEY_PLAYPAUSE, @@ -239,7 +239,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) dprintk(1,"%s: key event code=%d down=%d\n", dev->name,ir->keycode,ir->keypressed); input_report_key(dev,ir->keycode,ir->keypressed); - input_sync(dev); + input_sync(dev); } /* -------------------------------------------------------------------------- */ diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 76c1b63ebdf2..3e42493a4e0a 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -54,36 +54,36 @@ static struct i2c_driver driver; static struct i2c_client client_template; struct bt832 { - struct i2c_client client; + struct i2c_client client; }; int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) { int i,rc; buf[0]=0x80; // start at register 0 with auto-increment - if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) - printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); + if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) + printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); - for(i=0;i<65;i++) - buf[i]=0; - if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) - printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); + for(i=0;i<65;i++) + buf[i]=0; + if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) + printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); - // Note: On READ the first byte is the current index - // (e.g. 0x80, what we just wrote) + // Note: On READ the first byte is the current index + // (e.g. 0x80, what we just wrote) - if(1) { - int i; - printk("BT832 hexdump:\n"); - for(i=1;i<65;i++) { + if(1) { + int i; + printk("BT832 hexdump:\n"); + for(i=1;i<65;i++) { if(i!=1) { if(((i-1)%8)==0) printk(" "); - if(((i-1)%16)==0) printk("\n"); + if(((i-1)%16)==0) printk("\n"); } - printk(" %02x",buf[i]); - } - printk("\n"); - } + printk(" %02x",buf[i]); + } + printk("\n"); + } return 0; } @@ -102,13 +102,13 @@ int bt832_init(struct i2c_client *i2c_client_s) return 0; } - printk("Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + printk("Write 0 tp VPSTATUS\n"); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // Leave low power mode: @@ -116,17 +116,17 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[0]=BT832_CAM_SETUP0; //0x39 57 buf[1]=0x08; if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); + printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); printk("Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // Enable Output @@ -134,22 +134,22 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[0]=BT832_VP_CONTROL1; // Reg.40 buf[1]= 0x27 & (~0x01); // Default | !skip if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); + printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // for testing (even works when no camera attached) printk("bt832: *** Generate NTSC M Bars *****\n"); buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); printk("Bt832: Camera Present: %s\n", (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); kfree(buf); return 1; } @@ -162,17 +162,17 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) printk("bt832_attach\n"); - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - printk("bt832: chip found @ 0x%x\n", addr<<1); + printk("bt832: chip found @ 0x%x\n", addr<<1); - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; - i2c_set_clientdata(&t->client, t); - i2c_attach_client(&t->client); + i2c_set_clientdata(&t->client, t); + i2c_attach_client(&t->client); if(! bt832_init(&t->client)) { bt832_detach(&t->client); @@ -211,7 +211,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) printk("bt832: command %x\n",cmd); - switch (cmd) { + switch (cmd) { case BT832_HEXDUMP: { unsigned char *buf; buf=kmalloc(65,GFP_KERNEL); diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h index 9b6a8d2c96b5..1ce8fa71f7db 100644 --- a/drivers/media/video/bt832.h +++ b/drivers/media/video/bt832.h @@ -233,8 +233,8 @@ SetInterlaceMode( spec.interlace ); /* from web: Video Sampling Digital video is a sampled form of analog video. The most common sampling schemes in use today are: - Pixel Clock Horiz Horiz Vert - Rate Total Active + Pixel Clock Horiz Horiz Vert + Rate Total Active NTSC square pixel 12.27 MHz 780 640 525 NTSC CCIR-601 13.5 MHz 858 720 525 NTSC 4FSc 14.32 MHz 910 768 525 diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 3937da065e4f..92bb515fbe4d 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -6,7 +6,7 @@ like the big tvcards array for the most part Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2001 Gerd Knorr This program is free software; you can redistribute it and/or modify @@ -163,10 +163,10 @@ static struct CARD { { 0x6609107d, BTTV_BOARD_WINFAST2000, "Leadtek TV 2000 XP" }, { 0x263610b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x264510b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, + { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, { 0x405010fc, BTTV_BOARD_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, { 0x407010fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, { 0x001211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, /* some cards ship with byteswapped IDs ... */ @@ -277,7 +277,7 @@ static struct CARD { { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, - { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, + { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, { 0x40111554, BTTV_BOARD_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, { 0x17de0a01, BTTV_BOARD_KWORLD, "Mecer TV/FM/Video Tuner" }, @@ -1346,17 +1346,17 @@ struct tvcard bttv_tvcards[] = { }, [BTTV_BOARD_GMV1] = { /* Adrian Cox c.type = type; @@ -2929,7 +2929,7 @@ static void flyvideo_gpio(struct bttv *btv) switch(ttype) { case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */ break; - case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ + case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ break; case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ break; @@ -2945,7 +2945,7 @@ static void flyvideo_gpio(struct bttv *btv) has_radio = gpio & 0x400000; /* unknown 0x200000; * unknown2 0x100000; */ - is_capture_only = !(gpio & 0x008000); /* GPIO15 */ + is_capture_only = !(gpio & 0x008000); /* GPIO15 */ has_tda9820_tda9821 = !(gpio & 0x004000); is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */ /* @@ -2982,7 +2982,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) char *info; gpio_inout(0xffffff, 0); - gpio = gpio_read(); + gpio = gpio_read(); id = ((gpio>>10) & 63) -1; msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); if (id < 32) { @@ -3093,7 +3093,7 @@ static void eagle_muxsel(struct bttv *btv, unsigned int input) static void gvc1100_muxsel(struct bttv *btv, unsigned int input) { - static const int masks[] = {0x30, 0x01, 0x12, 0x23}; + static const int masks[] = {0x30, 0x01, 0x12, 0x23}; gpio_write(masks[input%4]); } @@ -3161,10 +3161,10 @@ void __devinit bttv_init_card1(struct bttv *btv) switch (btv->c.type) { case BTTV_BOARD_HAUPPAUGE: case BTTV_BOARD_HAUPPAUGE878: - boot_msp34xx(btv,5); + boot_msp34xx(btv,5); break; case BTTV_BOARD_VOODOOTV_FM: - boot_msp34xx(btv,20); + boot_msp34xx(btv,20); break; case BTTV_BOARD_AVERMEDIA98: boot_msp34xx(btv,11); @@ -3192,7 +3192,7 @@ void __devinit bttv_init_card2(struct bttv *btv) int tda9887; int addr=ADDR_UNSET, radio_addr=ADDR_UNSET; - btv->tuner_type = -1; + btv->tuner_type = -1; if (BTTV_BOARD_UNKNOWN == btv->c.type) { bttv_readee(btv,eeprom_data,0xa0); @@ -3225,7 +3225,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_HAUPPAUGEPVR: /* pick up some config infos from the eeprom */ bttv_readee(btv,eeprom_data,0xa0); - hauppauge_eeprom(btv); + hauppauge_eeprom(btv); break; case BTTV_BOARD_AVERMEDIA98: case BTTV_BOARD_AVPHONE98: @@ -3258,7 +3258,7 @@ void __devinit bttv_init_card2(struct bttv *btv) } break; case BTTV_BOARD_STB2: - if (btv->cardid == 0x3060121a) { + if (btv->cardid == 0x3060121a) { /* Fix up entry for 3DFX VoodooTV 100, which is an OEM STB card variant. */ btv->has_radio=0; @@ -3277,7 +3277,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_OSPREY540: case BTTV_BOARD_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); - osprey_eeprom(btv); + osprey_eeprom(btv); break; case BTTV_BOARD_IDS_EAGLE: init_ids_eagle(btv); @@ -3298,7 +3298,7 @@ void __devinit bttv_init_card2(struct bttv *btv) } /* pll configuration */ - if (!(btv->id==848 && btv->revision==0x11)) { + if (!(btv->id==848 && btv->revision==0x11)) { /* defaults from card list */ if (PLL_28 == bttv_tvcards[btv->c.type].pll) { btv->pll.pll_ifreq=28636363; @@ -3309,26 +3309,26 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->pll.pll_crystal=BT848_IFORM_XT1; } /* insmod options can override */ - switch (pll[btv->c.nr]) { - case 0: /* none */ + switch (pll[btv->c.nr]) { + case 0: /* none */ btv->pll.pll_crystal = 0; btv->pll.pll_ifreq = 0; btv->pll.pll_ofreq = 0; - break; - case 1: /* 28 MHz */ + break; + case 1: /* 28 MHz */ case 28: - btv->pll.pll_ifreq = 28636363; + btv->pll.pll_ifreq = 28636363; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT0; - break; - case 2: /* 35 MHz */ + btv->pll.pll_crystal = BT848_IFORM_XT0; + break; + case 2: /* 35 MHz */ case 35: - btv->pll.pll_ifreq = 35468950; + btv->pll.pll_ifreq = 35468950; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT1; - break; - } - } + btv->pll.pll_crystal = BT848_IFORM_XT1; + break; + } + } btv->pll.pll_current = -1; /* tuner configuration (from card list / autodetect / insmod option) */ @@ -3340,7 +3340,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) - btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; + btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); @@ -3348,14 +3348,14 @@ void __devinit bttv_init_card2(struct bttv *btv) bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; if (addr == radio_addr) - tun_setup.mode_mask = T_RADIO; + tun_setup.mode_mask = T_RADIO; bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } @@ -3433,11 +3433,11 @@ static void modtec_eeprom(struct bttv *btv) } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) { btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { - btv->tuner_type=TUNER_PHILIPS_NTSC; - printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); + btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { + btv->tuner_type=TUNER_PHILIPS_NTSC; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); } else { printk("bttv%d: Modtec: Unknown TunerString: %s\n", btv->c.nr,&eeprom_data[0x1e]); @@ -3502,7 +3502,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv) static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) { u32 n; - u8 bits; + u8 bits; int i; gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); @@ -3538,19 +3538,19 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) static int __devinit pvr_boot(struct bttv *btv) { - const struct firmware *fw_entry; + const struct firmware *fw_entry; int rc; rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); if (rc != 0) { printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", btv->c.nr); - return rc; - } + return rc; + } rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); printk(KERN_INFO "bttv%d: altera firmware upload %s\n", btv->c.nr, (rc < 0) ? "failed" : "ok"); - release_firmware(fw_entry); + release_firmware(fw_entry); return rc; } @@ -3564,33 +3564,33 @@ static void __devinit osprey_eeprom(struct bttv *btv) unsigned long serial = 0; if (btv->c.type == 0) { - /* this might be an antique... check for MMAC label in eeprom */ - if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { - unsigned char checksum = 0; - for (i =0; i<21; i++) + /* this might be an antique... check for MMAC label in eeprom */ + if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { + unsigned char checksum = 0; + for (i =0; i<21; i++) checksum += ee[i]; - if (checksum != ee[21]) + if (checksum != ee[21]) return; btv->c.type = BTTV_BOARD_OSPREY1x0_848; for (i = 12; i < 21; i++) serial *= 10, serial += ee[i] - '0'; - } + } } else { unsigned short type; - int offset = 4*16; - - for(; offset < 8*16; offset += 16) { - unsigned short checksum = 0; - /* verify the checksum */ - for(i = 0; i<14; i++) checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { - break; - } - } - - if (offset >= 8*16) + int offset = 4*16; + + for(; offset < 8*16; offset += 16) { + unsigned short checksum = 0; + /* verify the checksum */ + for(i = 0; i<14; i++) checksum += ee[i+offset]; + checksum = ~checksum; /* no idea why */ + if ((((checksum>>8)&0x0FF) == ee[offset+14]) && + ((checksum & 0x0FF) == ee[offset+15])) { + break; + } + } + + if (offset >= 8*16) return; /* found a valid descriptor */ @@ -3606,7 +3606,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) btv->c.type = BTTV_BOARD_OSPREY101_848; break; - /* 878 based */ + /* 878 based */ case 0x0012: case 0x0013: btv->c.type = BTTV_BOARD_OSPREY1x0; @@ -3662,27 +3662,27 @@ static void __devinit osprey_eeprom(struct bttv *btv) /* AVermedia specific stuff, from bktr_card.c */ static int tuner_0_table[] = { - TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, TUNER_PHILIPS_FM1216ME_MK3 }; static int tuner_1_table[] = { - TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, + TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, - TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ - TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; + TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ + TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; static void __devinit avermedia_eeprom(struct bttv *btv) { - int tuner_make,tuner_tv_fm,tuner_format,tuner=0; + int tuner_make,tuner_tv_fm,tuner_format,tuner=0; tuner_make = (eeprom_data[0x41] & 0x7); - tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; - tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; + tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; + tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; btv->has_remote = (eeprom_data[0x42] & 0x01); if (tuner_make == 0 || tuner_make == 2) @@ -3718,8 +3718,8 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) dprintk("bttv_tda9880_setnorm to NTSC\n"); } else { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; dprintk("bttv_tda9880_setnorm to PAL\n"); } /* set GPIO according */ @@ -3741,7 +3741,7 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin) gpio_inout(mask,mask); gpio_bits(mask,0); - udelay(2500); + udelay(2500); gpio_bits(mask,mask); if (bttv_gpio) @@ -3817,7 +3817,7 @@ static void __devinit init_PXC200(struct bttv *btv) udelay(10); gpio_write(1<<2); - for (i = 0; i < ARRAY_SIZE(vals); i++) { + for (i = 0; i < ARRAY_SIZE(vals); i++) { tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1); if (tmp != -1) { printk(KERN_INFO @@ -4260,30 +4260,30 @@ avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set) { - int val = 0; + int val = 0; - if (gpio_read() & 0x4000) { + if (gpio_read() & 0x4000) { v->mode = VIDEO_SOUND_MONO; return; } - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ - val = 0x0080; + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ + val = 0x0080; if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ - val = 0x0880; - if ((v->mode & VIDEO_SOUND_LANG1) || + val = 0x0880; + if ((v->mode & VIDEO_SOUND_LANG1) || (v->mode & VIDEO_SOUND_MONO)) val = 0; gpio_bits(0x0880, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"lt9415"); - } else { + if (bttv_gpio) + bttv_gpio_tracking(btv,"lt9415"); + } else { /* autodetect doesn't work with this card :-( */ - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } + return; + } } /* TDA9821 on TerraTV+ Bt848, Bt878 */ @@ -4406,26 +4406,26 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) static void windvr_audio(struct bttv *btv, struct video_audio *v, int set) { - unsigned long val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) - val = 0x040000; - if (v->mode & VIDEO_SOUND_LANG1) - val = 0; - if (v->mode & VIDEO_SOUND_LANG2) - val = 0x100000; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0; - if (val) { + unsigned long val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) + val = 0x040000; + if (v->mode & VIDEO_SOUND_LANG1) + val = 0; + if (v->mode & VIDEO_SOUND_LANG2) + val = 0x100000; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0; + if (val) { gpio_bits(0x140000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } + if (bttv_gpio) + bttv_gpio_tracking(btv,"windvr"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } } /* @@ -4668,10 +4668,10 @@ static void kodicom4400r_init(struct bttv *btv) static void xguard_muxsel(struct bttv *btv, unsigned int input) { static const int masks[] = { - ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, - ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, - ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, - ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, + ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, + ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, + ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, + ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, }; gpio_write(masks[input%16]); } @@ -4776,10 +4776,10 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input) static void PXC200_muxsel(struct bttv *btv, unsigned int input) { - int rc; + int rc; long mux; int bitmask; - unsigned char buf[2]; + unsigned char buf[2]; /* Read PIC config to determine if this is a PXC200F */ /* PX_I2C_CMD_CFG*/ @@ -4809,14 +4809,14 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) /* bitmask=0x30f; */ bitmask=0x302; /* check whether we have a PXC200A */ - if (btv->cardid == PX_PXC200A_CARDID) { + if (btv->cardid == PX_PXC200A_CARDID) { bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ bitmask |= 7<<4; /* the DAC */ } btwrite(bitmask, BT848_GPIO_OUT_EN); bitmask = btread(BT848_GPIO_DATA); - if (btv->cardid == PX_PXC200A_CARDID) + if (btv->cardid == PX_PXC200A_CARDID) bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); else /* older device */ bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); @@ -4829,7 +4829,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) * * needed because bttv-driver sets mux before calling this function */ - if (btv->cardid == PX_PXC200A_CARDID) + if (btv->cardid == PX_PXC200A_CARDID) btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); else /* older device */ btand(~BT848_IFORM_MUXSEL,BT848_IFORM); @@ -4875,7 +4875,7 @@ void __devinit bttv_check_chipset(void) printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency); while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, dev))) { - unsigned char b; + unsigned char b; pci_read_config_byte(dev, 0x53, &b); if (bttv_debug) printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, " @@ -4885,7 +4885,7 @@ void __devinit bttv_check_chipset(void) int __devinit bttv_handle_chipset(struct bttv *btv) { - unsigned char command; + unsigned char command; if (!triton1 && !vsfx && UNSET == latency) return 0; @@ -4906,13 +4906,13 @@ int __devinit bttv_handle_chipset(struct bttv *btv) btv->triton1 = BT848_INT_ETBF; } else { /* bt878 has a bit in the pci config space for it */ - pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); + pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); if (triton1) command |= BT878_EN_TBFX; if (vsfx) command |= BT878_EN_VSFX; - pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); - } + pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); + } if (UNSET != latency) pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); return 0; diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index f8307407e320..0005741d5514 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -3,7 +3,7 @@ bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler - & Marcus Metzler + & Marcus Metzler (c) 1999-2002 Gerd Knorr some v4l2 code lines are taken from Justin's bttv2 driver which is @@ -192,8 +192,8 @@ static u8 SRAM_Table[][60] = const struct bttv_tvnorm bttv_tvnorms[] = { /* PAL-BDGHI */ - /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ + /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ + /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ { .v4l2_id = V4L2_STD_PAL, .name = "PAL", @@ -806,9 +806,9 @@ static void bt848A_set_timing(struct bttv *btv) btv->c.nr,table_idx); /* timing change...reset timing generator address */ - btwrite(0x00, BT848_TGCTRL); - btwrite(0x02, BT848_TGCTRL); - btwrite(0x00, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); + btwrite(0x02, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); len=SRAM_Table[table_idx][0]; for(i = 1; i <= len; i++) @@ -847,7 +847,7 @@ static void bt848_hue(struct bttv *btv, int hue) /* -128 to 127 */ value = (hue >> 8) - 128; - btwrite(value & 0xff, BT848_HUE); + btwrite(value & 0xff, BT848_HUE); } static void bt848_contrast(struct bttv *btv, int cont) @@ -859,9 +859,9 @@ static void bt848_contrast(struct bttv *btv, int cont) /* 0-511 */ value = (cont >> 7); hibit = (value >> 6) & 4; - btwrite(value & 0xff, BT848_CONTRAST_LO); - btaor(hibit, ~4, BT848_E_CONTROL); - btaor(hibit, ~4, BT848_O_CONTROL); + btwrite(value & 0xff, BT848_CONTRAST_LO); + btaor(hibit, ~4, BT848_E_CONTROL); + btaor(hibit, ~4, BT848_O_CONTROL); } static void bt848_sat(struct bttv *btv, int color) @@ -873,12 +873,12 @@ static void bt848_sat(struct bttv *btv, int color) /* 0-511 for the color */ val_u = ((color * btv->opt_uv_ratio) / 50) >> 7; val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254; - hibits = (val_u >> 7) & 2; + hibits = (val_u >> 7) & 2; hibits |= (val_v >> 8) & 1; - btwrite(val_u & 0xff, BT848_SAT_U_LO); - btwrite(val_v & 0xff, BT848_SAT_V_LO); - btaor(hibits, ~3, BT848_E_CONTROL); - btaor(hibits, ~3, BT848_O_CONTROL); + btwrite(val_u & 0xff, BT848_SAT_U_LO); + btwrite(val_v & 0xff, BT848_SAT_V_LO); + btaor(hibits, ~3, BT848_E_CONTROL); + btaor(hibits, ~3, BT848_O_CONTROL); } /* ----------------------------------------------------------------------- */ @@ -891,7 +891,7 @@ video_mux(struct bttv *btv, unsigned int input) if (input >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; - /* needed by RemoteVideo MX */ + /* needed by RemoteVideo MX */ mask2 = bttv_tvcards[btv->c.type].gpiomask2; if (mask2) gpio_inout(mask2,mask2); @@ -1055,22 +1055,22 @@ static void init_bt848(struct bttv *btv) btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); - /* set planar and packed mode trigger points and */ - /* set rising edge of inverted GPINTR pin as irq trigger */ - btwrite(BT848_GPIO_DMA_CTL_PKTP_32| - BT848_GPIO_DMA_CTL_PLTP1_16| - BT848_GPIO_DMA_CTL_PLTP23_16| - BT848_GPIO_DMA_CTL_GPINTC| - BT848_GPIO_DMA_CTL_GPINTI, - BT848_GPIO_DMA_CTL); + /* set planar and packed mode trigger points and */ + /* set rising edge of inverted GPINTR pin as irq trigger */ + btwrite(BT848_GPIO_DMA_CTL_PKTP_32| + BT848_GPIO_DMA_CTL_PLTP1_16| + BT848_GPIO_DMA_CTL_PLTP23_16| + BT848_GPIO_DMA_CTL_GPINTC| + BT848_GPIO_DMA_CTL_GPINTI, + BT848_GPIO_DMA_CTL); val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; - btwrite(val, BT848_E_SCLOOP); - btwrite(val, BT848_O_SCLOOP); + btwrite(val, BT848_E_SCLOOP); + btwrite(val, BT848_O_SCLOOP); - btwrite(0x20, BT848_E_VSCALE_HI); - btwrite(0x20, BT848_O_VSCALE_HI); - btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), + btwrite(0x20, BT848_E_VSCALE_HI); + btwrite(0x20, BT848_O_VSCALE_HI); + btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), BT848_ADC); btwrite(whitecrush_upper, BT848_WC_UP); @@ -1089,7 +1089,7 @@ static void init_bt848(struct bttv *btv) bt848_contrast(btv, btv->contrast); bt848_sat(btv, btv->saturation); - /* interrupt */ + /* interrupt */ init_irqreg(btv); } @@ -1105,7 +1105,7 @@ static void bttv_reinit_bt848(struct bttv *btv) spin_unlock_irqrestore(&btv->s_lock,flags); init_bt848(btv); - btv->pll.pll_current = -1; + btv->pll.pll_current = -1; set_input(btv,btv->input); } @@ -1398,7 +1398,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, /* video4linux (1) interface */ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, - const struct bttv_format *fmt, + const struct bttv_format *fmt, unsigned int width, unsigned int height, enum v4l2_field field) { @@ -1521,8 +1521,8 @@ static const char *v4l1_ioctls[] = { static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { - case BTTV_VERSION: - return BTTV_VERSION_CODE; + case BTTV_VERSION: + return BTTV_VERSION_CODE; /* *** v4l1 *** ************************************************ */ case VIDIOCGFREQ: @@ -1576,32 +1576,32 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; + case VIDIOCGCHAN: + { + struct video_channel *v = arg; unsigned int channel = v->channel; - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - v->tuners=0; - v->flags = VIDEO_VC_AUDIO; - v->type = VIDEO_TYPE_CAMERA; - v->norm = btv->tvnorm; + if (channel >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + v->tuners=0; + v->flags = VIDEO_VC_AUDIO; + v->type = VIDEO_TYPE_CAMERA; + v->norm = btv->tvnorm; if (channel == bttv_tvcards[btv->c.type].tuner) { - strcpy(v->name,"Television"); - v->flags|=VIDEO_VC_TUNER; - v->type=VIDEO_TYPE_TV; - v->tuners=1; - } else if (channel == btv->svhs) { - strcpy(v->name,"S-Video"); - } else { - sprintf(v->name,"Composite%d",channel); + strcpy(v->name,"Television"); + v->flags|=VIDEO_VC_TUNER; + v->type=VIDEO_TYPE_TV; + v->tuners=1; + } else if (channel == btv->svhs) { + strcpy(v->name,"S-Video"); + } else { + sprintf(v->name,"Composite%d",channel); } return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; unsigned int channel = v->channel; if (channel >= bttv_tvcards[btv->c.type].video_inputs) @@ -1623,7 +1623,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOCGAUDIO: + case VIDIOCGAUDIO: { struct video_audio *v = arg; @@ -1728,7 +1728,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) } else if (i->index == btv->svhs) { sprintf(i->name, "S-Video"); } else { - sprintf(i->name,"Composite%d",i->index); + sprintf(i->name,"Composite%d",i->index); } if (i->index == btv->input) { __u32 dstatus = btread(BT848_DSTATUS); @@ -2168,7 +2168,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, if (0 != retval) return retval; if (locked_btres(fh->btv, RESOURCE_VBI)) - return -EBUSY; + return -EBUSY; bttv_vbi_try_fmt(fh,f); bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]); bttv_vbi_get_fmt(fh,f); @@ -2206,9 +2206,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bttv_reinit_bt848(btv); switch (cmd) { - case VIDIOCSFREQ: - case VIDIOCSTUNER: - case VIDIOCSCHAN: + case VIDIOCSFREQ: + case VIDIOCSTUNER: + case VIDIOCSCHAN: case VIDIOC_S_CTRL: case VIDIOC_S_STD: case VIDIOC_S_INPUT: @@ -2224,10 +2224,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* *** v4l1 *** ************************************************ */ case VIDIOCGCAP: { - struct video_capability *cap = arg; + struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev->name); + strcpy(cap->name,btv->video_dev->name); if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { /* vbi */ cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; @@ -2247,7 +2247,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } cap->channels = bttv_tvcards[btv->c.type].video_inputs; cap->audios = bttv_tvcards[btv->c.type].audio_inputs; - return 0; + return 0; } case VIDIOCGPICT: @@ -2296,7 +2296,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bt848_hue(btv,pic->hue); bt848_sat(btv,pic->colour); up(&fh->cap.lock); - return 0; + return 0; } case VIDIOCGWIN: @@ -2357,8 +2357,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, unsigned long end; if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; + !capable(CAP_SYS_RAWIO)) + return -EPERM; end = (unsigned long)fbuf->base + fbuf->height * fbuf->bytesperline; down(&fh->cap.lock); @@ -2432,7 +2432,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } /* switch over */ - retval = bttv_switch_overlay(btv,fh,new); + retval = bttv_switch_overlay(btv,fh,new); up(&fh->cap.lock); return retval; } @@ -2571,13 +2571,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGCHAN: - case VIDIOCSCHAN: + case BTTV_VERSION: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGCHAN: + case VIDIOCSCHAN: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return bttv_common_ioctls(btv,cmd,arg); @@ -2589,8 +2589,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 == v4l2) return -EINVAL; - strcpy(cap->driver,"bttv"); - strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); + strcpy(cap->driver,"bttv"); + strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci)); cap->version = BTTV_VERSION_CODE; cap->capabilities = @@ -3097,7 +3097,7 @@ static struct video_device bttv_video_template = { .name = "UNSET", .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, .minor = -1, @@ -3143,7 +3143,7 @@ static int radio_open(struct inode *inode, struct file *file) audio_mux(btv,AUDIO_RADIO); up(&btv->lock); - return 0; + return 0; } static int radio_release(struct inode *inode, struct file *file) @@ -3166,34 +3166,34 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case VIDIOCGCAP: { - struct video_capability *cap = arg; + struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev->name); - cap->type = VID_TYPE_TUNER; + strcpy(cap->name,btv->radio_dev->name); + cap->type = VID_TYPE_TUNER; cap->channels = 1; cap->audios = 1; - return 0; + return 0; } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; + if(v->tuner) + return -EINVAL; memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: + strcpy(v->name, "Radio"); + bttv_call_i2c_clients(btv,cmd,v); + return 0; + } + case VIDIOCSTUNER: /* nothing to do */ return 0; case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: + case VIDIOCGFREQ: + case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return bttv_common_ioctls(btv,cmd,arg); @@ -3699,7 +3699,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (astat&BT848_INT_VSYNC) - btv->field_count++; + btv->field_count++; if (astat & BT848_INT_GPINT) { wake_up(&btv->gpioq); @@ -3711,13 +3711,13 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) wake_up(&btv->i2c_queue); } - if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) bttv_irq_switch_vbi(btv); - if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) bttv_irq_wakeup_top(btv); - if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) bttv_irq_switch_video(btv); if ((astat & BT848_INT_HLOCK) && btv->opt_automute) @@ -3744,7 +3744,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (count > 4) { if (count > 8 || !(astat & BT848_INT_GPINT)) { - btwrite(0, BT848_INT_MASK); + btwrite(0, BT848_INT_MASK); printk(KERN_ERR "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); @@ -3826,7 +3826,7 @@ static int __devinit bttv_register_video(struct bttv *btv) /* video */ btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); - if (NULL == btv->video_dev) + if (NULL == btv->video_dev) goto err; if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) goto err; @@ -3836,18 +3836,18 @@ static int __devinit bttv_register_video(struct bttv *btv) /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); - if (NULL == btv->vbi_dev) + if (NULL == btv->vbi_dev) goto err; - if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) + if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", btv->c.nr,btv->vbi_dev->minor & 0x1f); - if (!btv->has_radio) + if (!btv->has_radio) return 0; /* radio */ btv->radio_dev = vdev_init(btv, &radio_template, "radio"); - if (NULL == btv->radio_dev) + if (NULL == btv->radio_dev) goto err; if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) goto err; @@ -3868,11 +3868,11 @@ static int __devinit bttv_register_video(struct bttv *btv) static void pci_set_command(struct pci_dev *dev) { #if defined(__powerpc__) - unsigned int cmd; + unsigned int cmd; - pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); - pci_write_config_dword(dev, PCI_COMMAND, cmd); + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + cmd = (cmd | PCI_COMMAND_MEMORY ); + pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif } @@ -3886,21 +3886,21 @@ static int __devinit bttv_probe(struct pci_dev *dev, if (bttv_num == BTTV_MAX) return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); - btv=&bttvs[bttv_num]; + btv=&bttvs[bttv_num]; memset(btv,0,sizeof(*btv)); btv->c.nr = bttv_num; sprintf(btv->c.name,"bttv%d",btv->c.nr); /* initialize structs / fill in defaults */ - init_MUTEX(&btv->lock); - init_MUTEX(&btv->reslock); - spin_lock_init(&btv->s_lock); - spin_lock_init(&btv->gpio_lock); - init_waitqueue_head(&btv->gpioq); - init_waitqueue_head(&btv->i2c_queue); - INIT_LIST_HEAD(&btv->c.subs); - INIT_LIST_HEAD(&btv->capture); - INIT_LIST_HEAD(&btv->vcapture); + init_MUTEX(&btv->lock); + init_MUTEX(&btv->reslock); + spin_lock_init(&btv->s_lock); + spin_lock_init(&btv->gpio_lock); + init_waitqueue_head(&btv->gpioq); + init_waitqueue_head(&btv->i2c_queue); + INIT_LIST_HEAD(&btv->c.subs); + INIT_LIST_HEAD(&btv->capture); + INIT_LIST_HEAD(&btv->vcapture); v4l2_prio_init(&btv->prio); init_timer(&btv->timeout); @@ -3921,27 +3921,27 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->c.nr); return -EIO; } - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", + if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", btv->c.nr); return -EIO; - } + } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), btv->c.name)) { - printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", + printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", btv->c.nr, pci_resource_start(dev,0)); return -EBUSY; } - pci_set_master(dev); + pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", - bttv_num,btv->id, btv->revision, pci_name(dev)); - printk("irq: %d, latency: %d, mmio: 0x%lx\n", + pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", + bttv_num,btv->id, btv->revision, pci_name(dev)); + printk("irq: %d, latency: %d, mmio: 0x%lx\n", btv->c.pci->irq, lat, pci_resource_start(dev,0)); schedule(); @@ -3952,23 +3952,23 @@ static int __devinit bttv_probe(struct pci_dev *dev, goto fail1; } - /* identify card */ + /* identify card */ bttv_idcard(btv); - /* disable irqs, register irq handler */ + /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); - result = request_irq(btv->c.pci->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); - if (result < 0) { - printk(KERN_ERR "bttv%d: can't get IRQ %d\n", + result = request_irq(btv->c.pci->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); + if (result < 0) { + printk(KERN_ERR "bttv%d: can't get IRQ %d\n", bttv_num,btv->c.pci->irq); goto fail1; - } + } if (0 != bttv_handle_chipset(btv)) { result = -EIO; goto fail2; - } + } /* init options from insmod args */ btv->opt_combfilter = combfilter; @@ -3994,29 +3994,29 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->input = 0; /* initialize hardware */ - if (bttv_gpio) - bttv_gpio_tracking(btv,"pre-init"); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pre-init"); bttv_risc_init_main(btv); init_bt848(btv); /* gpio */ - btwrite(0x00, BT848_GPIO_REG_INP); - btwrite(0x00, BT848_GPIO_OUT_EN); - if (bttv_verbose) - bttv_gpio_tracking(btv,"init"); + btwrite(0x00, BT848_GPIO_REG_INP); + btwrite(0x00, BT848_GPIO_OUT_EN); + if (bttv_verbose) + bttv_gpio_tracking(btv,"init"); - /* needs to be done before i2c is registered */ - bttv_init_card1(btv); + /* needs to be done before i2c is registered */ + bttv_init_card1(btv); - /* register i2c + gpio */ - init_bttv_i2c(btv); + /* register i2c + gpio */ + init_bttv_i2c(btv); - /* some card-specific stuff (needs working i2c) */ - bttv_init_card2(btv); + /* some card-specific stuff (needs working i2c) */ + bttv_init_card2(btv); init_irqreg(btv); - /* register video4linux + input */ + /* register video4linux + input */ if (!bttv_tvcards[btv->c.type].no_video) { bttv_register_video(btv); bt848_bright(btv,32768); @@ -4035,10 +4035,10 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* everything is fine */ bttv_num++; - return 0; + return 0; fail2: - free_irq(btv->c.pci->irq,btv); + free_irq(btv->c.pci->irq,btv); fail1: if (btv->bt848_mmio) @@ -4051,12 +4051,12 @@ static int __devinit bttv_probe(struct pci_dev *dev, static void __devexit bttv_remove(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); - /* shutdown everything (DMA+IRQs) */ + /* shutdown everything (DMA+IRQs) */ btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_INT_MASK); btwrite(~0x0, BT848_INT_STAT); @@ -4069,7 +4069,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) wake_up(&btv->gpioq); bttv_sub_del_devices(&btv->c); - /* unregister i2c_bus + input */ + /* unregister i2c_bus + input */ fini_bttv_i2c(btv); /* unregister video4linux */ @@ -4079,18 +4079,18 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) btcx_riscmem_free(btv->c.pci,&btv->main); /* free ressources */ - free_irq(btv->c.pci->irq,btv); + free_irq(btv->c.pci->irq,btv); iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->c.pci,0), - pci_resource_len(btv->c.pci,0)); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); pci_set_drvdata(pci_dev, NULL); - return; + return; } static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); struct bttv_buffer_set idle; unsigned long flags; @@ -4125,7 +4125,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) static int bttv_resume(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); unsigned long flags; int err; @@ -4170,24 +4170,24 @@ static int bttv_resume(struct pci_dev *pci_dev) } static struct pci_device_id bttv_pci_tbl[] = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); static struct pci_driver bttv_pci_driver = { - .name = "bttv", - .id_table = bttv_pci_tbl, - .probe = bttv_probe, - .remove = __devexit_p(bttv_remove), + .name = "bttv", + .id_table = bttv_pci_tbl, + .probe = bttv_probe, + .remove = __devexit_p(bttv_remove), .suspend = bttv_suspend, .resume = bttv_resume, }; diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 6b280c03e398..575ce8b8e714 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c @@ -7,7 +7,7 @@ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index e684df37eb0e..06c5965b5616 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -5,7 +5,7 @@ bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify @@ -237,7 +237,7 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) err: if (i2c_debug) printk(" ERR: %d\n",retval); - return retval; + return retval; } static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) @@ -290,7 +290,7 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { - struct bttv *btv = i2c_get_adapdata(client->adapter); + struct bttv *btv = i2c_get_adapdata(client->adapter); if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", @@ -300,9 +300,9 @@ static int attach_inform(struct i2c_client *client) return 0; if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = ADDR_UNSET; @@ -312,7 +312,7 @@ static int attach_inform(struct i2c_client *client) if (btv->pinnacle_id != UNSET) client->driver->command(client,AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); - return 0; + return 0; } void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) @@ -330,43 +330,43 @@ static struct i2c_client bttv_i2c_client_template = { /* read I2C */ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { - unsigned char buffer = 0; + unsigned char buffer = 0; if (0 != btv->i2c_rc) return -1; if (bttv_verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", btv->c.nr,probe_for,addr); - btv->i2c_client.addr = addr >> 1; - if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { + btv->i2c_client.addr = addr >> 1; + if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { if (NULL != probe_for) { if (bttv_verbose) printk("not found\n"); } else printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", btv->c.nr,addr); - return -1; + return -1; } if (bttv_verbose && NULL != probe_for) printk("found\n"); - return buffer; + return buffer; } /* write I2C */ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both) + unsigned char b2, int both) { - unsigned char buffer[2]; - int bytes = both ? 2 : 1; + unsigned char buffer[2]; + int bytes = both ? 2 : 1; if (0 != btv->i2c_rc) return -1; - btv->i2c_client.addr = addr >> 1; - buffer[0] = b1; - buffer[1] = b2; - if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) + btv->i2c_client.addr = addr >> 1; + buffer[0] = b1; + buffer[1] = b2; + if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) return -1; - return 0; + return 0; } /* read EEPROM content */ @@ -431,8 +431,8 @@ int __devinit init_bttv_i2c(struct bttv *btv) "bt%d #%d [%s]", btv->id, btv->c.nr, btv->use_i2c_hw ? "hw" : "sw"); - i2c_set_adapdata(&btv->c.i2c_adap, btv); - btv->i2c_client.adapter = &btv->c.i2c_adap; + i2c_set_adapdata(&btv->c.i2c_adap, btv); + btv->i2c_client.adapter = &btv->c.i2c_adap; #ifdef I2C_CLASS_TV_ANALOG if (bttv_tvcards[btv->c.type].no_video) diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c index e8aada772b89..19b564ab0e92 100644 --- a/drivers/media/video/bttv-if.c +++ b/drivers/media/video/bttv-if.c @@ -1,13 +1,13 @@ /* bttv-if.c -- old gpio interface to other kernel modules - don't use in new code, will go away in 2.7 + don't use in new code, will go away in 2.7 have a look at bttv-gpio.c instead. bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index a5ed99b89445..3028862934dd 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -74,27 +74,27 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, } if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| BT848_RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; } else { /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + todo = bpl; + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| todo); *(rp++)=cpu_to_le32(sg_dma_address(sg)); offset += todo; @@ -201,8 +201,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, ri |= BT848_RISC_EOL; /* write risc instruction */ - *(rp++)=cpu_to_le32(ri | ylen); - *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | + *(rp++)=cpu_to_le32(ri | ylen); + *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | (ylen >> hshift)); *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset); yoffset += ylen; @@ -319,7 +319,7 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, int width, int height, int interleaved, int norm) { const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; - u32 xsf, sr; + u32 xsf, sr; int vdelay; int swidth = tvnorm->swidth; @@ -334,52 +334,52 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, vdelay = tvnorm->vdelay; - xsf = (width*scaledtwidth)/swidth; - geo->hscale = ((totalwidth*4096UL)/xsf-4096); - geo->hdelay = tvnorm->hdelayx1; - geo->hdelay = (geo->hdelay*width)/swidth; - geo->hdelay &= 0x3fe; - sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; - geo->vscale = (0x10000UL-sr) & 0x1fff; - geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | - ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); - geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; - geo->vdelay = vdelay; - geo->width = width; - geo->sheight = tvnorm->sheight; + xsf = (width*scaledtwidth)/swidth; + geo->hscale = ((totalwidth*4096UL)/xsf-4096); + geo->hdelay = tvnorm->hdelayx1; + geo->hdelay = (geo->hdelay*width)/swidth; + geo->hdelay &= 0x3fe; + sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; + geo->vscale = (0x10000UL-sr) & 0x1fff; + geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | + ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); + geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; + geo->vdelay = vdelay; + geo->width = width; + geo->sheight = tvnorm->sheight; geo->vtotal = tvnorm->vtotal; - if (btv->opt_combfilter) { - geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); - geo->comb = (width < 769) ? 1 : 0; - } else { - geo->vtc = 0; - geo->comb = 0; - } + if (btv->opt_combfilter) { + geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + geo->comb = (width < 769) ? 1 : 0; + } else { + geo->vtc = 0; + geo->comb = 0; + } } static void bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) { - int off = odd ? 0x80 : 0x00; + int off = odd ? 0x80 : 0x00; if (geo->comb) btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); else btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - btwrite(geo->vtc, BT848_E_VTC+off); - btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); - btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); - btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); - btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); - btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); - btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); - btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); - btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); - btwrite(geo->crop, BT848_E_CROP+off); + btwrite(geo->vtc, BT848_E_VTC+off); + btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); + btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); + btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); + btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); + btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); + btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); + btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); + btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); + btwrite(geo->crop, BT848_E_CROP+off); btwrite(geo->vtotal>>8, BT848_VTOTAL_HI); - btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); + btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); } /* ---------------------------------------------------------- */ @@ -420,7 +420,7 @@ bttv_set_dma(struct bttv *btv, int override) } else { del_timer(&btv->timeout); } - btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); + btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); btaor(capctl, ~0x0f, BT848_CAP_CTL); if (capctl) { @@ -432,7 +432,7 @@ bttv_set_dma(struct bttv *btv, int override) } else { if (!btv->dma_on) return; - btand(~3, BT848_GPIO_DMA_CTL); + btand(~3, BT848_GPIO_DMA_CTL); btv->dma_on = 0; } return; @@ -460,19 +460,19 @@ bttv_risc_init_main(struct bttv *btv) btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); - btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | + btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | BT848_FIFO_STATUS_VRO); - btv->main.cpu[9] = cpu_to_le32(0); + btv->main.cpu[9] = cpu_to_le32(0); /* bottom field */ - btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); - btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); /* jump back to top field */ btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); + btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); return 0; } diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 26cd117a6df4..124ea41dada4 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -202,7 +202,7 @@ struct bttv_core { struct list_head subs; /* struct bttv_sub_device */ /* device config */ - unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ unsigned int type; /* card type (pointer into tvcards[]) */ char name[8]; /* dev name */ }; @@ -211,16 +211,16 @@ struct bttv; struct tvcard { - char *name; - unsigned int video_inputs; - unsigned int audio_inputs; - unsigned int tuner; - unsigned int svhs; + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO - u32 gpiomask; - u32 muxsel[16]; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ - u32 gpiomask2; /* GPIO MUX mask */ + u32 gpiomask; + u32 muxsel[16]; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask2; /* GPIO MUX mask */ /* i2c audio flags */ unsigned int no_msp34xx:1; diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index e0e7c7a84bc5..386f546f7d11 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -77,14 +77,14 @@ struct bttv_tvnorm { int v4l2_id; char *name; - u32 Fsc; - u16 swidth, sheight; /* scaled standard width, height */ + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ u16 totalwidth; u8 adelay, bdelay, iform; u32 scaledtwidth; u16 hdelayx1, hactivex1; u16 vdelay; - u8 vbipack; + u8 vbipack; u16 vtotal; int sram; }; @@ -267,8 +267,8 @@ struct bttv { /* card configuration info */ unsigned int cardid; /* pci subsystem id (bt878 based ones) */ - unsigned int tuner_type; /* tuner chip type */ - unsigned int pinnacle_id; + unsigned int tuner_type; /* tuner chip type */ + unsigned int pinnacle_id; unsigned int svhs; struct bttv_pll_info pll; int triton1; @@ -301,9 +301,9 @@ struct bttv { /* locking */ spinlock_t s_lock; - struct semaphore lock; + struct semaphore lock; int resources; - struct semaphore reslock; + struct semaphore reslock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index fac67d98a745..4ae3f78cccf2 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -436,7 +436,7 @@ static int memory_write(struct cx88_core *core, u32 address, u32 value) static int memory_read(struct cx88_core *core, u32 address, u32 *value) { - int retval; + int retval; u32 val; /* Warning: address is dword address (4 bytes) */ @@ -605,11 +605,11 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) u32 *dataptr; retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); msleep(1); - retval |= register_write(dev->core, IVTV_REG_APU, 0); + retval |= register_write(dev->core, IVTV_REG_APU, 0); if (retval < 0) dprintk(0, "Error with register_write\n"); @@ -657,13 +657,13 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) release_firmware(firmware); dprintk(0, "Firmware upload successful.\n"); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_read(dev->core, IVTV_REG_SPU, &value); - retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_read(dev->core, IVTV_REG_SPU, &value); + retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); msleep(1); retval |= register_read(dev->core, IVTV_REG_VPU, &value); - retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); + retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); if (retval < 0) dprintk(0, "Error with register_write\n"); @@ -876,7 +876,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) au_params |= 0; } else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; @@ -942,7 +942,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid - */ + */ } #define CHECK_PARAM( name ) ( dev->params.name != params->name ) #define IF_PARAM( name ) if( CHECK_PARAM( name ) ) @@ -1068,7 +1068,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * au_params |= 0; } else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; @@ -1150,7 +1150,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid - */ + */ UPDATE_PARAM( ts_pid_pmt ); UPDATE_PARAM( ts_pid_audio ); UPDATE_PARAM( ts_pid_video ); @@ -1712,7 +1712,7 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, static void __devexit blackbird_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* blackbird */ blackbird_unregister_video(dev); @@ -1728,8 +1728,8 @@ static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } @@ -1737,10 +1737,10 @@ static struct pci_device_id cx8802_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver blackbird_pci_driver = { - .name = "cx88-blackbird", - .id_table = cx8802_pci_tbl, - .probe = blackbird_probe, - .remove = __devexit_p(blackbird_remove), + .name = "cx88-blackbird", + .id_table = cx8802_pci_tbl, + .probe = blackbird_probe, + .remove = __devexit_p(blackbird_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cf17da836914..504917768794 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -126,27 +126,27 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x03ff, + .gpio0 = 0x03ff, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x03fe, + .gpio0 = 0x03fe, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0x03fe, + .gpio0 = 0x03fe, }}, }, - [CX88_BOARD_WINFAST2000XP_EXPERT] = { - .name = "Leadtek Winfast 2000XP Expert", - .tuner_type = TUNER_PHILIPS_4IN1, + [CX88_BOARD_WINFAST2000XP_EXPERT] = { + .name = "Leadtek Winfast 2000XP Expert", + .tuner_type = TUNER_PHILIPS_4IN1, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, .gpio0 = 0x00F5e700, .gpio1 = 0x00003004, .gpio2 = 0x00F5e700, @@ -165,15 +165,15 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x00003004, .gpio2 = 0x00F5c700, .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, + }}, + .radio = { + .type = CX88_RADIO, .gpio0 = 0x00F5d700, .gpio1 = 0x00003004, .gpio2 = 0x00F5d700, .gpio3 = 0x02000000, - }, - }, + }, + }, [CX88_BOARD_AVERTV_303] = { .name = "AverTV Studio 303 (M126)", .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -214,32 +214,32 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, - }}, - .radio = { + }}, + .radio = { .type = CX88_RADIO, - }, + }, }, [CX88_BOARD_WINFAST_DV2000] = { - .name = "Leadtek Winfast DV2000", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .name = "Leadtek Winfast DV2000", + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, .gpio0 = 0x0035e700, .gpio1 = 0x00003004, .gpio2 = 0x0035e700, @@ -260,14 +260,14 @@ struct cx88_board cx88_boards[] = { .gpio2 = 0x02000000, .gpio3 = 0x02000000, }}, - .radio = { + .radio = { .type = CX88_RADIO, .gpio0 = 0x0035d700, .gpio1 = 0x00007004, .gpio2 = 0x0035d700, .gpio3 = 0x02000000, }, - }, + }, [CX88_BOARD_LEADTEK_PVR2000] = { // gpio values for PAL version from regspy by DScaler .name = "Leadtek PVR 2000", @@ -296,25 +296,25 @@ struct cx88_board cx88_boards[] = { .blackbird = 1, }, [CX88_BOARD_IODATA_GVVCP3PCI] = { - .name = "IODATA GV-VCP3/PCI", + .name = "IODATA GV-VCP3/PCI", .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE2, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - }, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE2, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + }, [CX88_BOARD_PROLINK_PLAYTVPVR] = { - .name = "Prolink PlayTV PVR", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .name = "Prolink PlayTV PVR", + .tuner_type = TUNER_PHILIPS_FM1236_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -348,15 +348,15 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000fde6, - },{ + },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? }}, - .radio = { - .type = CX88_RADIO, + .radio = { + .type = CX88_RADIO, .gpio0 = 0x0000fde2, - }, + }, .blackbird = 1, }, [CX88_BOARD_MSI_TVANYWHERE] = { @@ -372,34 +372,34 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc08, },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc68, },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc68, - }}, + }}, }, - [CX88_BOARD_KWORLD_DVB_T] = { - .name = "KWorld/VStream XPert DVB-T", + [CX88_BOARD_KWORLD_DVB_T] = { + .name = "KWorld/VStream XPert DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x0700, .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x0700, .gpio2 = 0x0101, - }}, + }}, .dvb = 1, }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { @@ -425,27 +425,27 @@ struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x07f8, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x07f8, },{ .type = CX88_VMUX_DEBUG, .vmux = 0, .gpio0 = 0x07f9, // mono from tuner chip - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000007fa, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000007fa, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000007f8, - }, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000007fa, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000007fa, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000007f8, + }, }, [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = { .name = "DViCO FusionHDTV 3 Gold-Q", @@ -489,28 +489,28 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, - [CX88_BOARD_HAUPPAUGE_DVB_T1] = { + [CX88_BOARD_HAUPPAUGE_DVB_T1] = { .name = "Hauppauge Nova-T DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, .dvb = 1, }, - [CX88_BOARD_CONEXANT_DVB_T1] = { + [CX88_BOARD_CONEXANT_DVB_T1] = { .name = "Conexant DVB-T reference design", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, .dvb = 1, }, [CX88_BOARD_PROVIDEO_PV259] = { @@ -543,12 +543,12 @@ struct cx88_board cx88_boards[] = { .dvb = 1, }, [CX88_BOARD_DNTV_LIVE_DVB_T] = { - .name = "digitalnow DNTV Live! DVB-T", + .name = "digitalnow DNTV Live! DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ + .input = {{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00000700, @@ -705,44 +705,44 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0xbf60, }, }, - [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { + [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { .name = "DViCO FusionHDTV 3 Gold-T", .tuner_type = TUNER_THOMSON_DTT7611, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x97ed, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x97e9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x97e9, - }}, + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x97ed, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x97e9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x97e9, + }}, .dvb = 1, - }, - [CX88_BOARD_ADSTECH_DVB_T_PCI] = { - .name = "ADS Tech Instant TV DVB-T PCI", + }, + [CX88_BOARD_ADSTECH_DVB_T_PCI] = { + .name = "ADS Tech Instant TV DVB-T PCI", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x0700, .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x0700, .gpio2 = 0x0101, - }}, + }}, .dvb = 1, }, [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = { @@ -762,18 +762,18 @@ struct cx88_board cx88_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x87fd, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x87f9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x87f9, - }}, + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x87fd, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x87f9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x87f9, + }}, .dvb = 1, }, [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = { @@ -805,23 +805,23 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { /* Alexander Wold */ - .name = "Kworld V-Stream Xpert DVD", - .tuner_type = UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x03000000, - .gpio1 = 0x01000000, - .gpio2 = 0x02000000, - .gpio3 = 0x00100000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x03000000, + .name = "Kworld V-Stream Xpert DVD", + .tuner_type = UNSET, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x03000000, .gpio1 = 0x01000000, .gpio2 = 0x02000000, .gpio3 = 0x00100000, - }}, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x03000000, + .gpio1 = 0x01000000, + .gpio2 = 0x02000000, + .gpio3 = 0x00100000, + }}, }, [CX88_BOARD_ATI_HDTVWONDER] = { .name = "ATI HDTV Wonder", @@ -892,26 +892,26 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x00f8, .card = CX88_BOARD_ATI_WONDER_PRO, },{ - .subvendor = 0x107d, - .subdevice = 0x6611, - .card = CX88_BOARD_WINFAST2000XP_EXPERT, + .subvendor = 0x107d, + .subdevice = 0x6611, + .card = CX88_BOARD_WINFAST2000XP_EXPERT, + },{ + .subvendor = 0x107d, + .subdevice = 0x6613, /* NTSC */ + .card = CX88_BOARD_WINFAST2000XP_EXPERT, + },{ + .subvendor = 0x107d, + .subdevice = 0x6620, + .card = CX88_BOARD_WINFAST_DV2000, },{ - .subvendor = 0x107d, - .subdevice = 0x6613, /* NTSC */ - .card = CX88_BOARD_WINFAST2000XP_EXPERT, + .subvendor = 0x107d, + .subdevice = 0x663b, + .card = CX88_BOARD_LEADTEK_PVR2000, },{ .subvendor = 0x107d, - .subdevice = 0x6620, - .card = CX88_BOARD_WINFAST_DV2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663b, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663C, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ + .subdevice = 0x663C, + .card = CX88_BOARD_LEADTEK_PVR2000, + },{ .subvendor = 0x1461, .subdevice = 0x000b, .card = CX88_BOARD_AVERTV_303, @@ -920,13 +920,13 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x8606, .card = CX88_BOARD_MSI_TVANYWHERE_MASTER, },{ - .subvendor = 0x10fc, - .subdevice = 0xd003, - .card = CX88_BOARD_IODATA_GVVCP3PCI, + .subvendor = 0x10fc, + .subdevice = 0xd003, + .card = CX88_BOARD_IODATA_GVVCP3PCI, },{ - .subvendor = 0x1043, - .subdevice = 0x4823, /* with mpeg encoder */ - .card = CX88_BOARD_ASUS_PVR_416, + .subvendor = 0x1043, + .subdevice = 0x4823, /* with mpeg encoder */ + .card = CX88_BOARD_ASUS_PVR_416, },{ .subvendor = 0x17de, .subdevice = 0x08a6, @@ -943,15 +943,15 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xdb00, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, - },{ + },{ .subvendor = 0x0070, .subdevice = 0x9002, .card = CX88_BOARD_HAUPPAUGE_DVB_T1, - },{ + },{ .subvendor = 0x14f1, .subdevice = 0x0187, .card = CX88_BOARD_CONEXANT_DVB_T1, - },{ + },{ .subvendor = 0x1540, .subdevice = 0x2580, .card = CX88_BOARD_PROVIDEO_PV259, @@ -960,9 +960,9 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0xdb10, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, },{ - .subvendor = 0x1554, - .subdevice = 0x4811, - .card = CX88_BOARD_PIXELVIEW, + .subvendor = 0x1554, + .subdevice = 0x4811, + .card = CX88_BOARD_PIXELVIEW, },{ .subvendor = 0x7063, .subdevice = 0x3000, /* HD-3000 card */ @@ -987,23 +987,23 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1421, .subdevice = 0x0334, .card = CX88_BOARD_ADSTECH_DVB_T_PCI, - },{ + },{ .subvendor = 0x153b, .subdevice = 0x1166, .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, - },{ + },{ .subvendor = 0x18ac, .subdevice = 0xd500, .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, - },{ + },{ .subvendor = 0x1461, .subdevice = 0x8011, .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, - },{ + },{ .subvendor = PCI_VENDOR_ID_ATI, .subdevice = 0xa101, .card = CX88_BOARD_ATI_HDTVWONDER, - },{ + },{ .subvendor = 0x107d, .subdevice = 0x665f, .card = CX88_BOARD_WINFAST_DTV1000, diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index d4d39c1751af..f01a631d0c00 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -153,26 +153,26 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, } if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; } else { /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| + todo = bpl; + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); *(rp++)=cpu_to_le32(sg_dma_address(sg)); offset += todo; } @@ -309,7 +309,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video y / packed", .cmds_start = 0x180040, .ctrl_start = 0x180400, - .cdt = 0x180400 + 64, + .cdt = 0x180400 + 64, .fifo_start = 0x180c00, .fifo_size = 0x002800, .ptr1_reg = MO_DMA21_PTR1, @@ -321,7 +321,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video u", .cmds_start = 0x180080, .ctrl_start = 0x1804a0, - .cdt = 0x1804a0 + 64, + .cdt = 0x1804a0 + 64, .fifo_start = 0x183400, .fifo_size = 0x000800, .ptr1_reg = MO_DMA22_PTR1, @@ -333,7 +333,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video v", .cmds_start = 0x1800c0, .ctrl_start = 0x180540, - .cdt = 0x180540 + 64, + .cdt = 0x180540 + 64, .fifo_start = 0x183c00, .fifo_size = 0x000800, .ptr1_reg = MO_DMA23_PTR1, @@ -345,7 +345,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "vbi", .cmds_start = 0x180100, .ctrl_start = 0x1805e0, - .cdt = 0x1805e0 + 64, + .cdt = 0x1805e0 + 64, .fifo_start = 0x184400, .fifo_size = 0x001000, .ptr1_reg = MO_DMA24_PTR1, @@ -357,7 +357,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "audio from", .cmds_start = 0x180140, .ctrl_start = 0x180680, - .cdt = 0x180680 + 64, + .cdt = 0x180680 + 64, .fifo_start = 0x185400, .fifo_size = 0x000200, .ptr1_reg = MO_DMA25_PTR1, @@ -369,7 +369,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "audio to", .cmds_start = 0x180180, .ctrl_start = 0x180720, - .cdt = 0x180680 + 64, /* same as audio IN */ + .cdt = 0x180680 + 64, /* same as audio IN */ .fifo_start = 0x185400, /* same as audio IN */ .fifo_size = 0x000200, /* same as audio IN */ .ptr1_reg = MO_DMA26_PTR1, @@ -1137,7 +1137,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) if (!core->radio_addr) core->radio_addr = cx88_boards[core->board].radio_addr; - printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", + printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", core->tuner_type, core->tuner_addr<<1, core->radio_type, core->radio_addr<<1); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 579de88e3081..3be601cfc99b 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -128,7 +128,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) static u8 reset [] = { 0x50, 0x80 }; static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; + 0x00, 0xFF, 0x00, 0x40, 0x40 }; static u8 dntv_extra[] = { 0xB5, 0x7A }; static u8 capt_range_cfg[] = { 0x75, 0x32 }; @@ -464,7 +464,7 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, static void __devexit dvb_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* dvb */ videobuf_dvb_unregister(&dev->dvb); @@ -479,8 +479,8 @@ static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } @@ -488,10 +488,10 @@ static struct pci_device_id cx8802_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver dvb_pci_driver = { - .name = "cx88-dvb", - .id_table = cx8802_pci_tbl, - .probe = dvb_probe, - .remove = __devexit_p(dvb_remove), + .name = "cx88-dvb", + .id_table = cx8802_pci_tbl, + .probe = dvb_probe, + .remove = __devexit_p(dvb_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 761cebd40dbd..9790d412f192 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -3,7 +3,7 @@ cx88-i2c.c -- all the i2c code is here Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 2002 Yurij Sysoev (c) 1999-2003 Gerd Knorr @@ -90,7 +90,7 @@ static int cx8800_bit_getsda(void *data) static int attach_inform(struct i2c_client *client) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; struct cx88_core *core = i2c_get_adapdata(client->adapter); dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", @@ -98,7 +98,7 @@ static int attach_inform(struct i2c_client *client) if (!client->driver->command) return 0; - if (core->radio_type != UNSET) { + if (core->radio_type != UNSET) { if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) { tun_setup.mode_mask = T_RADIO; tun_setup.type = core->radio_type; @@ -106,8 +106,8 @@ static int attach_inform(struct i2c_client *client) client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } - } - if (core->tuner_type != UNSET) { + } + if (core->tuner_type != UNSET) { if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) { tun_setup.mode_mask = T_ANALOG_TV; @@ -116,7 +116,7 @@ static int attach_inform(struct i2c_client *client) client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } if (core->tda9887_conf) client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); @@ -159,7 +159,7 @@ static struct i2c_adapter cx8800_i2c_adap_template = { }; static struct i2c_client cx8800_i2c_client_template = { - .name = "cx88xx internal", + .name = "cx88xx internal", }; static char *i2c_devs[128] = { @@ -202,10 +202,10 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); - core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap,core); - core->i2c_adap.algo_data = &core->i2c_algo; - core->i2c_client.adapter = &core->i2c_adap; + core->i2c_algo.data = core; + i2c_set_adapdata(&core->i2c_adap,core); + core->i2c_adap.algo_data = &core->i2c_algo; + core->i2c_client.adapter = &core->i2c_adap; cx8800_bit_setscl(core,1); cx8800_bit_setsda(core,1); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index c27fe4c36f69..38b12ebaa49e 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -553,7 +553,7 @@ void cx88_ir_irq(struct cx88_core *core) if ((ircode & 0xffff) != 0xeb04) { /* wrong address */ ir_dprintk("pulse distance decoded wrong address\n"); - break; + break; } if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */ diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 2c4fbe9258d9..35e6d0c2b872 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -316,14 +316,14 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) spin_unlock(&dev->slock); } - /* other general errors */ - if (status & 0x1f0100) { + /* other general errors */ + if (status & 0x1f0100) { dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); - spin_lock(&dev->slock); + spin_lock(&dev->slock); cx8802_stop_dma(dev); - cx8802_restart_queue(dev,&dev->mpegq); - spin_unlock(&dev->slock); - } + cx8802_restart_queue(dev,&dev->mpegq); + spin_unlock(&dev->slock); + } } #define MAX_IRQ_LOOP 10 @@ -379,8 +379,8 @@ int cx8802_init_common(struct cx8802_dev *dev) } pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", dev->core->name, pci_name(dev->pci), dev->pci_rev, dev->pci->irq, dev->pci_lat,pci_resource_start(dev->pci,0)); @@ -430,7 +430,7 @@ void cx8802_fini_common(struct cx8802_dev *dev) int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); struct cx88_core *core = dev->core; /* stop mpeg dma */ diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index 0a3a62fc9bbb..d3bf5b17b1d4 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h @@ -3,9 +3,9 @@ cx88x-hw.h - CX2388x register offsets Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - 2001 Michael Eskin - 2002 Yurij Sysoev - 2003 Gerd Knorr + 2001 Michael Eskin + 2002 Yurij Sysoev + 2003 Gerd Knorr 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 @@ -728,13 +728,13 @@ #define ColorFormatGamma 0x1000 #define Interlaced 0x1 -#define NonInterlaced 0x0 +#define NonInterlaced 0x0 #define FieldEven 0x1 #define FieldOdd 0x0 -#define TGReadWriteMode 0x0 -#define TGEnableMode 0x1 +#define TGReadWriteMode 0x0 +#define TGEnableMode 0x1 #define DV_CbAlign 0x0 #define DV_Y0Align 0x1 diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 4c99fc39bb2a..f22ccb65de1c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -100,7 +100,7 @@ static struct cx88_tvnorm tvnorms[] = { .id = V4L2_STD_PAL_I, .cxiformat = VideoFormatPAL, .cxoformat = 0x181f0008, - },{ + },{ .name = "PAL-M", .id = V4L2_STD_PAL_M, .cxiformat = VideoFormatPALM, @@ -470,7 +470,7 @@ static int restart_video_queue(struct cx8800_dev *dev, struct list_head *item; if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); dprintk(2,"restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); start_video_dma(dev, q, buf); @@ -486,7 +486,7 @@ static int restart_video_queue(struct cx8800_dev *dev, for (;;) { if (list_empty(&q->queued)) return 0; - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); + buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); if (NULL == prev) { list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue,&q->active); @@ -783,7 +783,7 @@ static int video_open(struct inode *inode, struct file *file) cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); } - return 0; + return 0; } static ssize_t @@ -922,7 +922,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) { /* struct cx88_core *core = dev->core; */ struct cx88_ctrl *c = NULL; - u32 v_sat_value; + u32 v_sat_value; u32 value; int i; @@ -1252,7 +1252,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, - struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) + struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) { int err; @@ -1399,7 +1399,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, cx88_get_stereo(core ,t); reg = cx_read(MO_DEVICE_STATUS); - t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; + t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; return 0; } case VIDIOC_S_TUNER: @@ -1486,7 +1486,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "cx8800"); + strcpy(cap->driver, "cx8800"); strlcpy(cap->card, cx88_boards[core->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); @@ -1827,8 +1827,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", core->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); @@ -1944,7 +1944,7 @@ fail_free: static void __devexit cx8800_finidev(struct pci_dev *pci_dev) { - struct cx8800_dev *dev = pci_get_drvdata(pci_dev); + struct cx8800_dev *dev = pci_get_drvdata(pci_dev); struct cx88_core *core = dev->core; /* stop thread */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index ea5c092a779e..baeae1ac992c 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -259,8 +259,8 @@ struct cx88_core { /* pci stuff */ int pci_bus; int pci_slot; - u32 __iomem *lmmio; - u8 __iomem *bmmio; + u32 __iomem *lmmio; + u8 __iomem *bmmio; u32 shadow[SHADOW_MAX]; int pci_irqmask; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 59f8fa0bea60..f0860532575a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2,8 +2,8 @@ em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index f7b8fb035c9e..227a47d6e4bd 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -2,8 +2,8 @@ em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -33,32 +33,32 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -unsigned int core_debug = 0; +unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); #define em2820_coredbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) -unsigned int reg_debug = 0; +unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); #define em2820_regdbg(fmt, arg...) do {\ - if (reg_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (reg_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) -unsigned int isoc_debug = 0; +unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); #define em2820_isocdbg(fmt, arg...) do {\ - if (isoc_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (isoc_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) static int alt = EM2820_PINOUT; module_param(alt, int, 0644); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index f6bfc038777e..bfe0d8795b6d 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -2,8 +2,8 @@ em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index ba367a9796e7..8681a793a0bf 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -43,34 +43,34 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); /* ---------------------------------------------------------------------- */ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_KP1, + [ 0x06 ] = KEY_KP2, + [ 0x07 ] = KEY_KP3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_KP4, + [ 0x0a ] = KEY_KP5, + [ 0x0b ] = KEY_KP6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_KP7, + [ 0x0e ] = KEY_KP8, + [ 0x0f ] = KEY_KP9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_KP0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, [ 0x1b ] = KEY_FORWARD, [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 048ad1d77bab..e5066d05697e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2,8 +2,8 @@ em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -42,9 +42,9 @@ #define EM2820_VERSION_CODE KERNEL_VERSION(0, 0, 1) #define em2820_videodbg(fmt, arg...) do {\ - if (video_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (video_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index a11df04a8c3d..c48354062eb6 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -2,8 +2,8 @@ em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -390,17 +390,17 @@ extern const unsigned int em2820_bcount; /* printk macros */ #define em2820_err(fmt, arg...) do {\ - printk(KERN_ERR fmt , ##arg); } while (0) + printk(KERN_ERR fmt , ##arg); } while (0) #define em2820_errdev(fmt, arg...) do {\ - printk(KERN_ERR "%s: "fmt,\ + printk(KERN_ERR "%s: "fmt,\ dev->name , ##arg); } while (0) #define em2820_info(fmt, arg...) do {\ - printk(KERN_INFO "%s: "fmt,\ + printk(KERN_INFO "%s: "fmt,\ dev->name , ##arg); } while (0) #define em2820_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s: "fmt,\ + printk(KERN_WARNING "%s: "fmt,\ dev->name , ##arg); } while (0) inline static int em2820_audio_source(struct em2820 *dev, int input) diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index cc5973950c05..ed81934ef3cd 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -369,14 +369,14 @@ static int ir_probe(struct device *dev) ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms - break; + break; case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms - break; + break; case BTTV_BOARD_WINFAST2000: ir_codes = ir_codes_winfast; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index b0facaa40b2f..12f1053137da 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -163,7 +163,7 @@ static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -177,7 +177,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -225,7 +225,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -287,17 +287,17 @@ static int ir_detach(struct i2c_client *client); static int ir_probe(struct i2c_adapter *adap); static struct i2c_driver driver = { - .name = "ir remote kbd driver", - .id = I2C_DRIVERID_EXP3, /* FIXME */ - .flags = I2C_DF_NOTIFY, - .attach_adapter = ir_probe, - .detach_client = ir_detach, + .name = "ir remote kbd driver", + .id = I2C_DRIVERID_EXP3, /* FIXME */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = ir_probe, + .detach_client = ir_detach, }; static struct i2c_client client_template = { - .name = "unset", - .driver = &driver + .name = "unset", + .driver = &driver }; static int ir_attach(struct i2c_adapter *adap, int addr, @@ -398,7 +398,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, static int ir_detach(struct i2c_client *client) { - struct IR_i2c *ir = i2c_get_clientdata(client); + struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ del_timer(&ir->timer); diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 5573f68ce457..699cea2cc648 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -192,7 +192,7 @@ static int msp3400c_reset(struct i2c_client *client) (2 != i2c_transfer(client->adapter,test,2)) ) { printk(KERN_ERR "msp3400: chip reset failed\n"); return -1; - } + } return 0; } @@ -200,16 +200,16 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) { int err,retval; - unsigned char write[3]; - unsigned char read[2]; - struct i2c_msg msgs[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read } - }; + unsigned char write[3]; + unsigned char read[2]; + struct i2c_msg msgs[2] = { + { client->addr, 0, 3, write }, + { client->addr, I2C_M_RD, 2, read } + }; - write[0] = dev+1; - write[1] = addr >> 8; - write[2] = addr & 0xff; + write[0] = dev+1; + write[1] = addr >> 8; + write[2] = addr & 0xff; for (err = 0; err < 3;) { if (2 == i2c_transfer(client->adapter,msgs,2)) @@ -236,13 +236,13 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val) { int err; - unsigned char buffer[5]; + unsigned char buffer[5]; - buffer[0] = dev; - buffer[1] = addr >> 8; - buffer[2] = addr & 0xff; - buffer[3] = val >> 8; - buffer[4] = val & 0xff; + buffer[0] = dev; + buffer[1] = addr >> 8; + buffer[2] = addr & 0xff; + buffer[3] = val >> 8; + buffer[4] = val & 0xff; dprintk_trace("trace: msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val); @@ -812,7 +812,7 @@ static void watch_stereo(struct i2c_client *client) else if (msp->stereo & VIDEO_SOUND_LANG1) msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); else - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); } if (once) @@ -1512,21 +1512,21 @@ static struct i2c_client client_template = static int msp_attach(struct i2c_adapter *adap, int addr, int kind) { struct msp3400c *msp; - struct i2c_client *c; + struct i2c_client *c; int (*thread_func)(void *data) = NULL; int i; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - if (-1 == msp3400c_reset(&client_template)) { - dprintk("msp34xx: no chip found\n"); - return -1; - } + if (-1 == msp3400c_reset(&client_template)) { + dprintk("msp34xx: no chip found\n"); + return -1; + } - if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) - return -ENOMEM; - memcpy(c,&client_template,sizeof(struct i2c_client)); + if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + return -ENOMEM; + memcpy(c,&client_template,sizeof(struct i2c_client)); if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) { kfree(c); return -ENOMEM; @@ -1618,7 +1618,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } /* done */ - i2c_attach_client(c); + i2c_attach_client(c); /* update our own array */ for (i = 0; i < MSP3400_MAX; i++) { @@ -1739,7 +1739,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); - __u16 *sarg = arg; + __u16 *sarg = arg; int scart = 0; switch (cmd) { @@ -1969,7 +1969,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } msp_any_detect_stereo(client); - if (msp->audmode == V4L2_TUNER_MODE_STEREO) { + if (msp->audmode == V4L2_TUNER_MODE_STEREO) { a->capability=V4L2_AUDCAP_STEREO; } @@ -2005,7 +2005,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); } - if (sarg->capability==V4L2_AUDCAP_STEREO) { + if (sarg->capability==V4L2_AUDCAP_STEREO) { msp->audmode = V4L2_TUNER_MODE_STEREO; } else { msp->audmode &= ~V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 972aa5e0aeef..13b61c4dcbf8 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -76,17 +76,17 @@ static int mt2032_compute_freq(struct i2c_client *c, unsigned int xogc) //all in Hz { struct tuner *t = i2c_get_clientdata(c); - unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, + unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; - fref= 5250 *1000; //5.25MHz + fref= 5250 *1000; //5.25MHz desired_lo1=rfin+if1; lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); - lo1n=lo1/8; - lo1a=lo1-(lo1n*8); + lo1n=lo1/8; + lo1a=lo1-(lo1n*8); - s=rfin/1000/1000+1090; + s=rfin/1000/1000+1090; if(optimize_vco) { if(s>1890) sel=0; @@ -96,34 +96,34 @@ static int mt2032_compute_freq(struct i2c_client *c, else sel=4; // >1090 } else { - if(s>1790) sel=0; // <1958 - else if(s>1617) sel=1; - else if(s>1449) sel=2; - else if(s>1291) sel=3; - else sel=4; // >1090 + if(s>1790) sel=0; // <1958 + else if(s>1617) sel=1; + else if(s>1449) sel=2; + else if(s>1291) sel=3; + else sel=4; // >1090 } *ret_sel=sel; - lo1freq=(lo1a+8*lo1n)*fref; + lo1freq=(lo1a+8*lo1n)*fref; tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", rfin,lo1,lo1n,lo1a,sel,lo1freq); - desired_lo2=lo1freq-rfin-if2; - lo2=(desired_lo2)/fref; - lo2n=lo2/8; - lo2a=lo2-(lo2n*8); - lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith - lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; + desired_lo2=lo1freq-rfin-if2; + lo2=(desired_lo2)/fref; + lo2n=lo2/8; + lo2a=lo2-(lo2n*8); + lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith + lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", rfin,lo2,lo2n,lo2a,lo2num,lo2freq); - if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { + if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", lo1a, lo1n, lo2a,lo2n); - return(-1); - } + return(-1); + } mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to); // should recalculate lo1 (one step up/down) @@ -135,10 +135,10 @@ static int mt2032_compute_freq(struct i2c_client *c, buf[3]=0x0f; //reserved buf[4]=0x1f; buf[5]=(lo2n-1) | (lo2a<<5); - if(rfin >400*1000*1000) - buf[6]=0xe4; - else - buf[6]=0xf4; // set PKEN per rev 1.2 + if(rfin >400*1000*1000) + buf[6]=0xe4; + else + buf[6]=0xf4; // set PKEN per rev 1.2 buf[7]=8+xogc; buf[8]=0xc3; //reserved buf[9]=0x4e; //reserved @@ -168,7 +168,7 @@ static int mt2032_check_lo_lock(struct i2c_client *c) tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); udelay(1000); } - return lock; + return lock; } static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) @@ -202,7 +202,7 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) buf[0]=0x0f; buf[1]=sel; - i2c_master_send(c,buf,2); + i2c_master_send(c,buf,2); lock=mt2032_check_lo_lock(c); return lock; } @@ -219,23 +219,23 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", rfin,if1,if2,from,to); - buf[0]=0; - ret=i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,21); + buf[0]=0; + ret=i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,21); buf[0]=0; ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); if (ret<0) return; - // send only the relevant registers per Rev. 1.2 - buf[0]=0; - ret=i2c_master_send(c,buf,4); - buf[5]=5; - ret=i2c_master_send(c,buf+5,4); - buf[11]=11; - ret=i2c_master_send(c,buf+11,3); - if(ret!=3) + // send only the relevant registers per Rev. 1.2 + buf[0]=0; + ret=i2c_master_send(c,buf,4); + buf[5]=5; + ret=i2c_master_send(c,buf+5,4); + buf[11]=11; + ret=i2c_master_send(c,buf+11,3); + if(ret!=3) tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); // wait for PLLs to lock (per manual), retry LINT if not. @@ -253,7 +253,7 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, mdelay(10); buf[1]=8+t->xogc; i2c_master_send(c,buf,2); - } + } if (lock!=6) tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); @@ -284,7 +284,7 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) if2 = 38900*1000; } - mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, + mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, 1090*1000*1000, if2, from, to); } @@ -294,7 +294,7 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) int if2 = t->radio_if2; // per Manual for FM tuning: first if center freq. 1085 MHz - mt2032_set_if_freq(c, freq * 1000 / 16, + mt2032_set_if_freq(c, freq * 1000 / 16, 1085*1000*1000,if2,if2,if2); } @@ -302,57 +302,57 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) static int mt2032_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - unsigned char buf[21]; - int ret,xogc,xok=0; + unsigned char buf[21]; + int ret,xogc,xok=0; // Initialize Registers per spec. - buf[1]=2; // Index to register 2 - buf[2]=0xff; - buf[3]=0x0f; - buf[4]=0x1f; - ret=i2c_master_send(c,buf+1,4); - - buf[5]=6; // Index register 6 - buf[6]=0xe4; - buf[7]=0x8f; - buf[8]=0xc3; - buf[9]=0x4e; - buf[10]=0xec; - ret=i2c_master_send(c,buf+5,6); - - buf[12]=13; // Index register 13 - buf[13]=0x32; - ret=i2c_master_send(c,buf+12,2); - - // Adjust XOGC (register 7), wait for XOK - xogc=7; - do { + buf[1]=2; // Index to register 2 + buf[2]=0xff; + buf[3]=0x0f; + buf[4]=0x1f; + ret=i2c_master_send(c,buf+1,4); + + buf[5]=6; // Index register 6 + buf[6]=0xe4; + buf[7]=0x8f; + buf[8]=0xc3; + buf[9]=0x4e; + buf[10]=0xec; + ret=i2c_master_send(c,buf+5,6); + + buf[12]=13; // Index register 13 + buf[13]=0x32; + ret=i2c_master_send(c,buf+12,2); + + // Adjust XOGC (register 7), wait for XOK + xogc=7; + do { + tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); + mdelay(10); + buf[0]=0x0e; + i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,1); + xok=buf[0]&0x01; + tuner_dbg("mt2032: xok = 0x%02x\n",xok); + if (xok == 1) break; + + xogc--; tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); - mdelay(10); - buf[0]=0x0e; - i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,1); - xok=buf[0]&0x01; - tuner_dbg("mt2032: xok = 0x%02x\n",xok); - if (xok == 1) break; - - xogc--; - tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); - if (xogc == 3) { - xogc=4; // min. 4 per spec - break; - } - buf[0]=0x07; - buf[1]=0x88 + xogc; - ret=i2c_master_send(c,buf,2); - if (ret!=2) + if (xogc == 3) { + xogc=4; // min. 4 per spec + break; + } + buf[0]=0x07; + buf[1]=0x88 + xogc; + ret=i2c_master_send(c,buf,2); + if (ret!=2) tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); - } while (xok != 1 ); + } while (xok != 1 ); t->xogc=xogc; t->tv_freq = mt2032_set_tv_freq; t->radio_freq = mt2032_set_radio_freq; - return(1); + return(1); } static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) @@ -426,7 +426,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned } ret=i2c_master_send(c,buf,6); - if (ret!=6) + if (ret!=6) tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); } @@ -437,11 +437,11 @@ static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) if (t->std & V4L2_STD_525_60) { // NTSC - if2 = 45750*1000; - } else { - // PAL - if2 = 38900*1000; - } + if2 = 45750*1000; + } else { + // PAL + if2 = 38900*1000; + } if (V4L2_TUNER_DIGITAL_TV == t->mode) { // DVB (pinnacle 300i) if2 = 36150*1000; @@ -487,7 +487,7 @@ int microtune_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); char *name; - unsigned char buf[21]; + unsigned char buf[21]; int company_code; memset(buf,0,sizeof(buf)); @@ -496,17 +496,17 @@ int microtune_init(struct i2c_client *c) t->standby = NULL; name = "unknown"; - i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,21); - if (tuner_debug) { - int i; + i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,21); + if (tuner_debug) { + int i; tuner_dbg("MT20xx hexdump:"); - for(i=0;i<21;i++) { - printk(" %02x",buf[i]); - if(((i+1)%8)==0) printk(" "); - } - printk("\n"); - } + for(i=0;i<21;i++) { + printk(" %02x",buf[i]); + if(((i+1)%8)==0) printk(" "); + } + printk("\n"); + } company_code = buf[0x11] << 8 | buf[0x12]; tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", company_code,buf[0x13],buf[0x14]); @@ -525,8 +525,8 @@ int microtune_init(struct i2c_client *c) default: tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", name); - return 0; - } + return 0; + } strlcpy(c->name, name, sizeof(c->name)); tuner_info("microtune %s found, OK\n",name); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 37653ee87235..ed16282fca51 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -464,8 +464,8 @@ saa7113_command (struct i2c_client *client, /* standard i2c insmod options */ static unsigned short normal_i2c[] = { - I2C_SAA7113>>1, /* saa7113 */ - I2C_CLIENT_END + I2C_SAA7113>>1, /* saa7113 */ + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index dac720ea3b06..2bf5cf79eec1 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -169,31 +169,31 @@ static int saa6752hs_chip_command(struct i2c_client* client, /* execute the command */ switch(command) { - case SAA6752HS_COMMAND_RESET: - buf[0] = 0x00; + case SAA6752HS_COMMAND_RESET: + buf[0] = 0x00; break; case SAA6752HS_COMMAND_STOP: - buf[0] = 0x03; + buf[0] = 0x03; break; case SAA6752HS_COMMAND_START: - buf[0] = 0x02; + buf[0] = 0x02; break; case SAA6752HS_COMMAND_PAUSE: - buf[0] = 0x04; + buf[0] = 0x04; break; case SAA6752HS_COMMAND_RECONFIGURE: buf[0] = 0x05; break; - case SAA6752HS_COMMAND_SLEEP: - buf[0] = 0x06; + case SAA6752HS_COMMAND_SLEEP: + buf[0] = 0x06; break; - case SAA6752HS_COMMAND_RECONFIGURE_FORCE: + case SAA6752HS_COMMAND_RECONFIGURE_FORCE: buf[0] = 0x07; break; @@ -201,13 +201,13 @@ static int saa6752hs_chip_command(struct i2c_client* client, return -EINVAL; } - /* set it and wait for it to be so */ + /* set it and wait for it to be so */ i2c_master_send(client, buf, 1); timeout = jiffies + HZ * 3; for (;;) { /* get the current status */ buf[0] = 0x10; - i2c_master_send(client, buf, 1); + i2c_master_send(client, buf, 1); i2c_master_recv(client, buf, 1); if (!(buf[0] & 0x20)) @@ -223,14 +223,14 @@ static int saa6752hs_chip_command(struct i2c_client* client, /* delay a bit to let encoder settle */ msleep(50); - return status; + return status; } static int saa6752hs_set_bitrate(struct i2c_client* client, struct v4l2_mpeg_compression* params) { - u8 buf[3]; + u8 buf[3]; /* set the bitrate mode */ buf[0] = 0x71; @@ -242,31 +242,31 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, /* set the target bitrate */ buf[0] = 0x80; buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); /* set the max bitrate */ buf[0] = 0x81; buf[1] = params->vi_bitrate.max >> 8; - buf[2] = params->vi_bitrate.max & 0xff; + buf[2] = params->vi_bitrate.max & 0xff; i2c_master_send(client, buf, 3); } else { /* set the target bitrate (no max bitrate for CBR) */ - buf[0] = 0x81; + buf[0] = 0x81; buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); } /* set the audio bitrate */ - buf[0] = 0x94; + buf[0] = 0x94; buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; i2c_master_send(client, buf, 2); /* set the total bitrate */ buf[0] = 0xb1; - buf[1] = params->st_bitrate.target >> 8; - buf[2] = params->st_bitrate.target & 0xff; + buf[1] = params->st_bitrate.target >> 8; + buf[2] = params->st_bitrate.target & 0xff; i2c_master_send(client, buf, 3); return 0; @@ -386,8 +386,8 @@ static int saa6752hs_init(struct i2c_client* client) buf[1] = 0x01; i2c_master_send(client, buf, 2); - /* set bitrate */ - saa6752hs_set_bitrate(client, &h->params); + /* set bitrate */ + saa6752hs_set_bitrate(client, &h->params); /* Set GOP structure {3, 13} */ buf[0] = 0x72; @@ -426,9 +426,9 @@ static int saa6752hs_init(struct i2c_client* client) localPAT[sizeof(PAT) - 1] = crc & 0xFF; /* compute PMT */ - memcpy(localPMT, PMT, sizeof(PMT)); - localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); - localPMT[4] = h->params.ts_pid_pmt & 0xff; + memcpy(localPMT, PMT, sizeof(PMT)); + localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); + localPMT[4] = h->params.ts_pid_pmt & 0xff; localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); localPMT[16] = h->params.ts_pid_pcr & 0xFF; localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F); @@ -453,7 +453,7 @@ static int saa6752hs_init(struct i2c_client* client) buf[2] = h->params.ts_pid_video & 0xFF; i2c_master_send(client,buf,3); - /* Set PCR PID */ + /* Set PCR PID */ buf[0] = 0xC4; buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; buf[2] = h->params.ts_pid_pcr & 0xFF; @@ -467,7 +467,7 @@ static int saa6752hs_init(struct i2c_client* client) buf[0] = 0xa4; buf[1] = 1; i2c_master_send(client, buf, 2); - buf[1] = 0; + buf[1] = 0; i2c_master_send(client, buf, 2); /* start it going */ @@ -510,10 +510,10 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) { struct saa6752hs_state *h; - printk("saa6752hs: chip found @ 0x%x\n", addr<<1); + printk("saa6752hs: chip found @ 0x%x\n", addr<<1); - if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) + return -ENOMEM; memset(h,0,sizeof(*h)); h->client = client_template; h->params = param_defaults; @@ -552,7 +552,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_mpeg_compression *params = arg; int err = 0; - switch (cmd) { + switch (cmd) { case VIDIOC_S_MPEGCOMP: if (NULL == params) { /* apply settings and start encoder */ @@ -566,7 +566,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case VIDIOC_G_FMT: { - struct v4l2_format *f = arg; + struct v4l2_format *f = arg; if (h->video_format == SAA6752HS_VF_UNKNOWN) h->video_format = SAA6752HS_VF_D1; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 465beac941d7..e9ffe8f144ac 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -80,11 +80,11 @@ typedef struct snd_card_saa7134 { spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; - struct pci_dev *pci; - struct saa7134_dev *saadev; + struct pci_dev *pci; + struct saa7134_dev *saadev; - unsigned long iobase; - int irq; + unsigned long iobase; + int irq; spinlock_t lock; } snd_card_saa7134_t; @@ -94,7 +94,7 @@ typedef struct snd_card_saa7134 { */ typedef struct snd_card_saa7134_pcm { - struct saa7134_dev *saadev; + struct saa7134_dev *saadev; spinlock_t lock; unsigned int pcm_size; /* buffer size */ @@ -118,9 +118,9 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; static void saa7134_dma_stop(struct saa7134_dev *dev) { - dev->oss.dma_blk = -1; - dev->oss.dma_running = 0; - saa7134_set_dmabits(dev); + dev->oss.dma_blk = -1; + dev->oss.dma_running = 0; + saa7134_set_dmabits(dev); } /* @@ -135,9 +135,9 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) static void saa7134_dma_start(struct saa7134_dev *dev) { - dev->oss.dma_blk = 0; - dev->oss.dma_running = 1; - saa7134_set_dmabits(dev); + dev->oss.dma_blk = 0; + dev->oss.dma_running = 1; + saa7134_set_dmabits(dev); } /* @@ -184,28 +184,28 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) goto done; } - /* next block addr */ - next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; - saa_writel(reg,next_blk * dev->oss.blksize); - if (alsa_debug > 2) - dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", - (status & 0x10000000) ? "even" : "odd ", next_blk, - next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); + /* next block addr */ + next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; + saa_writel(reg,next_blk * dev->oss.blksize); + if (alsa_debug > 2) + dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", + (status & 0x10000000) ? "even" : "odd ", next_blk, + next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); - /* update status & wake waiting readers */ - dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; - dev->oss.read_count += dev->oss.blksize; + /* update status & wake waiting readers */ + dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; + dev->oss.read_count += dev->oss.blksize; - dev->oss.recording_on = reg; + dev->oss.recording_on = reg; if (dev->oss.read_count >= snd_pcm_lib_period_bytes(dev->oss.substream)) { - spin_unlock(&dev->slock); - snd_pcm_period_elapsed(dev->oss.substream); - spin_lock(&dev->slock); + spin_unlock(&dev->slock); + snd_pcm_period_elapsed(dev->oss.substream); + spin_lock(&dev->slock); } done: - spin_unlock(&dev->slock); + spin_unlock(&dev->slock); } @@ -239,23 +239,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) { - if (blksize < 0x100) - blksize = 0x100; - if (blksize > 0x10000) - blksize = 0x10000; - - if (blocks < 2) - blocks = 2; - if ((blksize * blocks) > 1024*1024) - blocks = 1024*1024 / blksize; - - dev->oss.blocks = blocks; - dev->oss.blksize = blksize; - dev->oss.bufsize = blksize * blocks; - - dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", - blocks,blksize,blksize * blocks / 1024); - return 0; + if (blksize < 0x100) + blksize = 0x100; + if (blksize > 0x10000) + blksize = 0x10000; + + if (blocks < 2) + blocks = 2; + if ((blksize * blocks) > 1024*1024) + blocks = 1024*1024 / blksize; + + dev->oss.blocks = blocks; + dev->oss.blksize = blksize; + dev->oss.bufsize = blksize * blocks; + + dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", + blocks,blksize,blksize * blocks / 1024); + return 0; } /* @@ -271,16 +271,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) static int dsp_buffer_init(struct saa7134_dev *dev) { - int err; - - if (!dev->oss.bufsize) - BUG(); - videobuf_dma_init(&dev->oss.dma); - err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); - if (0 != err) - return err; - return 0; + int err; + + if (!dev->oss.bufsize) + BUG(); + videobuf_dma_init(&dev->oss.dma); + err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + if (0 != err) + return err; + return 0; } /* @@ -298,18 +298,18 @@ static int dsp_buffer_init(struct saa7134_dev *dev) static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; - int err, bswap, sign; - u32 fmt, control; - unsigned long flags; + int err, bswap, sign; + u32 fmt, control; + unsigned long flags; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - struct saa7134_dev *dev; + struct saa7134_dev *dev; snd_card_saa7134_pcm_t *saapcm = runtime->private_data; unsigned int bps; - unsigned long size; - unsigned count; + unsigned long size; + unsigned count; - size = snd_pcm_lib_buffer_bytes(substream); - count = snd_pcm_lib_period_bytes(substream); + size = snd_pcm_lib_buffer_bytes(substream); + count = snd_pcm_lib_period_bytes(substream); saapcm->saadev->oss.substream = substream; bps = runtime->rate * runtime->channels; @@ -324,123 +324,123 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) dev=saa7134->saadev; - dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); + dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); - err = dsp_buffer_init(dev); - if (0 != err) - goto fail2; + err = dsp_buffer_init(dev); + if (0 != err) + goto fail2; - /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) - return err; - if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) - goto fail1; - if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, - 0))) - goto fail2; + /* prepare buffer */ + if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) + return err; + if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) + goto fail1; + if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) + goto fail2; - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: fmt = 0x00; break; - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: + case SNDRV_PCM_FORMAT_U16_LE: + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: fmt = 0x01; break; - default: - err = -EINVAL; - return 1; - } - - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: + default: + err = -EINVAL; + return 1; + } + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_S8: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: sign = 1; break; - default: + default: sign = 0; break; - } + } - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S16_BE: + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_BE: bswap = 1; break; - default: + default: bswap = 0; break; - } - - switch (dev->pci->device) { - case PCI_DEVICE_ID_PHILIPS_SAA7134: - if (1 == runtime->channels) - fmt |= (1 << 3); - if (2 == runtime->channels) - fmt |= (3 << 3); - if (sign) - fmt |= 0x04; - - fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; - saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); - saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); - saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); - saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); - - break; - case PCI_DEVICE_ID_PHILIPS_SAA7133: - case PCI_DEVICE_ID_PHILIPS_SAA7135: - if (1 == runtime->channels) - fmt |= (1 << 4); - if (2 == runtime->channels) - fmt |= (2 << 4); - if (!sign) - fmt |= 0x04; - saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); - saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); - //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); - break; - } - - dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", - runtime->format, runtime->channels, fmt, - bswap ? 'b' : '-'); - /* dma: setup channel 6 (= AUDIO) */ - control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (dev->oss.pt.dma >> 12); - if (bswap) - control |= SAA7134_RS_CONTROL_BSWAP; + } + + switch (dev->pci->device) { + case PCI_DEVICE_ID_PHILIPS_SAA7134: + if (1 == runtime->channels) + fmt |= (1 << 3); + if (2 == runtime->channels) + fmt |= (3 << 3); + if (sign) + fmt |= 0x04; + + fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; + saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); + saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); + saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); + saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); + + break; + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + if (1 == runtime->channels) + fmt |= (1 << 4); + if (2 == runtime->channels) + fmt |= (2 << 4); + if (!sign) + fmt |= 0x04; + saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); + saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); + //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); + break; + } + + dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", + runtime->format, runtime->channels, fmt, + bswap ? 'b' : '-'); + /* dma: setup channel 6 (= AUDIO) */ + control = SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->oss.pt.dma >> 12); + if (bswap) + control |= SAA7134_RS_CONTROL_BSWAP; /* I should be able to use runtime->dma_addr in the control - byte, but it doesn't work. So I allocate the DMA using the - V4L functions, and force ALSA to use that as the DMA area */ + byte, but it doesn't work. So I allocate the DMA using the + V4L functions, and force ALSA to use that as the DMA area */ runtime->dma_area = dev->oss.dma.vmalloc; - saa_writel(SAA7134_RS_BA1(6),0); - saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); - saa_writel(SAA7134_RS_PITCH(6),0); - saa_writel(SAA7134_RS_CONTROL(6),control); + saa_writel(SAA7134_RS_BA1(6),0); + saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); + saa_writel(SAA7134_RS_PITCH(6),0); + saa_writel(SAA7134_RS_CONTROL(6),control); dev->oss.rate = runtime->rate; - /* start dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_start(dev); - spin_unlock_irqrestore(&dev->slock,flags); + /* start dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_start(dev); + spin_unlock_irqrestore(&dev->slock,flags); return 0; fail2: - saa7134_pgtable_free(dev->pci,&dev->oss.pt); + saa7134_pgtable_free(dev->pci,&dev->oss.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); - return err; + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + return err; } @@ -465,10 +465,10 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * if (dev->oss.read_count) { - dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); - dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); - if (dev->oss.read_offset == dev->oss.bufsize) - dev->oss.read_offset = 0; + dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); + dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); + if (dev->oss.read_offset == dev->oss.bufsize) + dev->oss.read_offset = 0; } return bytes_to_frames(runtime, dev->oss.read_offset); @@ -480,9 +480,9 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * static snd_pcm_hardware_t snd_card_saa7134_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, @@ -550,16 +550,16 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->oss.blksize) - BUG(); + if (!dev->oss.blksize) + BUG(); - videobuf_dma_free(&dev->oss.dma); + videobuf_dma_free(&dev->oss.dma); - dev->oss.blocks = 0; - dev->oss.blksize = 0; - dev->oss.bufsize = 0; + dev->oss.blocks = 0; + dev->oss.blksize = 0; + dev->oss.bufsize = 0; - return 0; + return 0; } /* @@ -574,21 +574,21 @@ static int dsp_buffer_free(struct saa7134_dev *dev) static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) { - snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); + snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = chip->saadev; - unsigned long flags; + unsigned long flags; - /* stop dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_stop(dev); - spin_unlock_irqrestore(&dev->slock,flags); + /* stop dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_stop(dev); + spin_unlock_irqrestore(&dev->slock,flags); - /* unlock buffer */ - saa7134_pgtable_free(dev->pci,&dev->oss.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + /* unlock buffer */ + saa7134_pgtable_free(dev->pci,&dev->oss.pt); + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); - dsp_buffer_free(dev); - return 0; + dsp_buffer_free(dev); + return 0; } /* @@ -605,18 +605,18 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; snd_card_saa7134_pcm_t *saapcm; - snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - struct saa7134_dev *dev = saa7134->saadev; + snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); + struct saa7134_dev *dev = saa7134->saadev; int err; down(&dev->oss.lock); - dev->oss.afmt = SNDRV_PCM_FORMAT_U8; - dev->oss.channels = 2; - dev->oss.read_count = 0; - dev->oss.read_offset = 0; + dev->oss.afmt = SNDRV_PCM_FORMAT_U8; + dev->oss.channels = 2; + dev->oss.read_count = 0; + dev->oss.read_offset = 0; - up(&dev->oss.lock); + up(&dev->oss.lock); saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); if (saapcm == NULL) @@ -630,8 +630,8 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) runtime->private_free = snd_card_saa7134_runtime_free; runtime->hw = snd_card_saa7134_capture; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; + if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + return err; return 0; } @@ -723,7 +723,7 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ right = 20; spin_lock_irqsave(&chip->mixer_lock, flags); change = chip->mixer_volume[addr][0] != left || - chip->mixer_volume[addr][1] != right; + chip->mixer_volume[addr][1] != right; chip->mixer_volume[addr][0] = left; chip->mixer_volume[addr][1] = right; spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -764,7 +764,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ unsigned long flags; int change, addr = kcontrol->private_value; int left, right; - u32 anabar, xbarin; + u32 anabar, xbarin; int analog_io, rate; struct saa7134_dev *dev; @@ -775,7 +775,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ spin_lock_irqsave(&chip->mixer_lock, flags); change = chip->capture_source[addr][0] != left || - chip->capture_source[addr][1] != right; + chip->capture_source[addr][1] != right; chip->capture_source[addr][0] = left; chip->capture_source[addr][1] = right; dev->oss.input=addr; @@ -783,57 +783,57 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ if (change) { - switch (dev->pci->device) { + switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: - switch (addr) { - case MIXER_ADDR_TVTUNER: - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); - break; - case MIXER_ADDR_LINE1: - case MIXER_ADDR_LINE2: - analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; - rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; - saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); - break; - } - - break; + switch (addr) { + case MIXER_ADDR_TVTUNER: + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); + break; + case MIXER_ADDR_LINE1: + case MIXER_ADDR_LINE2: + analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; + rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; + saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); + break; + } + + break; case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: - xbarin = 0x03; // adc + xbarin = 0x03; // adc anabar = 0; - switch (addr) { - case MIXER_ADDR_TVTUNER: - xbarin = 0; // Demodulator - anabar = 2; // DACs - break; - case MIXER_ADDR_LINE1: - anabar = 0; // aux1, aux1 - break; - case MIXER_ADDR_LINE2: - anabar = 9; // aux2, aux2 - break; - } + switch (addr) { + case MIXER_ADDR_TVTUNER: + xbarin = 0; // Demodulator + anabar = 2; // DACs + break; + case MIXER_ADDR_LINE1: + anabar = 0; // aux1, aux1 + break; + case MIXER_ADDR_LINE2: + anabar = 9; // aux2, aux2 + break; + } /* output xbar always main channel */ - saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); + saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); if (left || right) { // We've got data, turn the input on - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); - saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); + saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); } else { - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); - saa_writel(SAA7133_ANALOG_IO_SELECT, 0); + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); + saa_writel(SAA7133_ANALOG_IO_SELECT, 0); } break; } - } + } return change; } @@ -878,8 +878,8 @@ static int snd_saa7134_free(snd_card_saa7134_t *chip) static int snd_saa7134_dev_free(snd_device_t *device) { - snd_card_saa7134_t *chip = device->device_data; - return snd_saa7134_free(chip); + snd_card_saa7134_t *chip = device->device_data; + return snd_saa7134_free(chip); } /* @@ -896,12 +896,12 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) snd_card_t *card; snd_card_saa7134_t *chip; int err; - static snd_device_ops_t ops = { - .dev_free = snd_saa7134_dev_free, - }; + static snd_device_ops_t ops = { + .dev_free = snd_saa7134_dev_free, + }; - if (dev >= SNDRV_CARDS) - return -ENODEV; + if (dev >= SNDRV_CARDS) + return -ENODEV; if (!enable[dev]) return -ENODEV; @@ -918,24 +918,24 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) /* Card "creation" */ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - return -ENOMEM; - } + if (chip == NULL) { + return -ENOMEM; + } - spin_lock_init(&chip->lock); + spin_lock_init(&chip->lock); - chip->saadev = saadev; + chip->saadev = saadev; - chip->card = card; + chip->card = card; - chip->pci = saadev->pci; - chip->irq = saadev->pci->irq; - chip->iobase = pci_resource_start(saadev->pci, 0); + chip->pci = saadev->pci; + chip->irq = saadev->pci->irq; + chip->iobase = pci_resource_start(saadev->pci, 0); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_saa7134_free(chip); - return err; - } + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + snd_saa7134_free(chip); + return err; + } if ((err = snd_card_saa7134_new_mixer(chip)) < 0) goto __nodev; @@ -943,15 +943,15 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) goto __nodev; - spin_lock_init(&chip->mixer_lock); + spin_lock_init(&chip->mixer_lock); snd_card_set_dev(card, &chip->pci->dev); /* End of "creation" */ strcpy(card->shortname, "SAA7134"); - sprintf(card->longname, "%s at 0x%lx irq %d", - chip->saadev->name, chip->iobase, chip->irq); + sprintf(card->longname, "%s at 0x%lx irq %d", + chip->saadev->name, chip->iobase, chip->irq); if ((err = snd_card_register(card)) == 0) { snd_saa7134_cards[dev] = card; @@ -966,8 +966,8 @@ __nodev: void alsa_card_saa7134_exit(void) { - int idx; - for (idx = 0; idx < SNDRV_CARDS; idx++) { - snd_card_free(snd_saa7134_cards[idx]); + int idx; + for (idx = 0; idx < SNDRV_CARDS; idx++) { + snd_card_free(snd_saa7134_cards[idx]); } } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 17b0549f2e1b..a60d49af341d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2114,16 +2114,16 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_409FM] = { - /* , Sergey */ - .name = "Beholder BeholdTV 409 FM", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .inputs = {{ - .name = name_tv, + /* , Sergey */ + .name = "Beholder BeholdTV 409 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, .vmux = 3, .amux = TV, .tv = 1, @@ -2131,60 +2131,60 @@ struct saa7134_board saa7134_boards[] = { .name = name_comp1, .vmux = 1, .amux = LINE1, - },{ - .name = name_svideo, + },{ + .name = name_svideo, .vmux = 8, .amux = LINE1, - }}, - .radio = { - .name = name_radio, + }}, + .radio = { + .name = name_radio, .amux = LINE2, - }, - }, - [SAA7134_BOARD_GOTVIEW_7135] = { + }, + }, + [SAA7134_BOARD_GOTVIEW_7135] = { /* Mike Baikov */ /* Andrey Cvetcov */ - .name = "GoTView 7135 PCI", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0x00200003, - .inputs = {{ - .name = name_tv, - .vmux = 1, - .amux = TV, - .tv = 1, - .gpio = 0x00200003, - },{ - .name = name_tv_mono, - .vmux = 1, - .amux = LINE2, - .gpio = 0x00200003, - },{ - .name = name_comp1, - .vmux = 3, - .amux = LINE1, - .gpio = 0x00200003, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE1, - .gpio = 0x00200003, - }}, - .radio = { - .name = name_radio, - .amux = LINE2, - .gpio = 0x00200003, - }, - .mute = { - .name = name_mute, - .amux = TV, - .gpio = 0x00200003, - }, - }, + .name = "GoTView 7135 PCI", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00200003, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x00200003, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x00200003, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x00200003, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x00200003, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x00200003, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x00200003, + }, + }, [SAA7134_BOARD_PHILIPS_EUROPA] = { .name = "Philips EUROPA V3 reference design", .audio_clock = 0x00187de7, @@ -2251,78 +2251,78 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, - [SAA7134_BOARD_RTD_VFG7350] = { - .name = "RTD Embedded Technologies VFG7350", - .audio_clock = 0x00200000, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .inputs = {{ - .name = "Composite 0", - .vmux = 0, - .amux = LINE1, - },{ - .name = "Composite 1", - .vmux = 1, - .amux = LINE2, - },{ - .name = "Composite 2", - .vmux = 2, - .amux = LINE1, - },{ - .name = "Composite 3", - .vmux = 3, - .amux = LINE2, - },{ - .name = "S-Video 0", - .vmux = 8, - .amux = LINE1, - },{ - .name = "S-Video 1", - .vmux = 9, - .amux = LINE2, - }}, - .mpeg = SAA7134_MPEG_EMPRESS, - .video_out = CCIR656, + [SAA7134_BOARD_RTD_VFG7350] = { + .name = "RTD Embedded Technologies VFG7350", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + .mpeg = SAA7134_MPEG_EMPRESS, + .video_out = CCIR656, .vid_port_opts = ( SET_T_CODE_POLARITY_NON_INVERTED | SET_CLOCK_NOT_DELAYED | SET_CLOCK_INVERTED | SET_VSYNC_OFF ), - }, - [SAA7134_BOARD_RTD_VFG7330] = { - .name = "RTD Embedded Technologies VFG7330", - .audio_clock = 0x00200000, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .inputs = {{ - .name = "Composite 0", - .vmux = 0, - .amux = LINE1, - },{ - .name = "Composite 1", - .vmux = 1, - .amux = LINE2, - },{ - .name = "Composite 2", - .vmux = 2, - .amux = LINE1, - },{ - .name = "Composite 3", - .vmux = 3, - .amux = LINE2, - },{ - .name = "S-Video 0", - .vmux = 8, - .amux = LINE1, - },{ - .name = "S-Video 1", - .vmux = 9, - .amux = LINE2, - }}, - }, + }, + [SAA7134_BOARD_RTD_VFG7330] = { + .name = "RTD Embedded Technologies VFG7330", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + }, [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = { .name = "LifeView FlyTV Platinum Mini2", .audio_clock = 0x00200000, @@ -2760,55 +2760,55 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */ .subdevice = 0x4091, .driver_data = SAA7134_BOARD_BEHOLD_409FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5456, /* GoTView */ - .subdevice = 0x7135, - .driver_data = SAA7134_BOARD_GOTVIEW_7135, - },{ + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5456, /* GoTView */ + .subdevice = 0x7135, + .driver_data = SAA7134_BOARD_GOTVIEW_7135, + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, .driver_data = SAA7134_BOARD_PHILIPS_EUROPA, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x185b, .subdevice = 0xc900, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x185b, .subdevice = 0xc901, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7350, - .driver_data = SAA7134_BOARD_RTD_VFG7350, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7330, - .driver_data = SAA7134_BOARD_RTD_VFG7330, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, - .subdevice = 0x1044, - .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, - },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7350, + .driver_data = SAA7134_BOARD_RTD_VFG7350, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7330, + .driver_data = SAA7134_BOARD_RTD_VFG7330, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, + .subdevice = 0x1044, + .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1131, .subdevice = 0x4ee9, .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, - },{ + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -3051,7 +3051,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: /* The Philips EUROPA based hybrid boards have the tuner connected through * the channel decoder. We have to make it transparent to find it - */ + */ { struct tuner_setup tun_setup; u8 data[] = { 0x07, 0x02}; @@ -3063,7 +3063,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) tun_setup.addr = dev->tuner_addr; saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); - } + } break; } return 0; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 907dbd4de7c9..afa0cfce6578 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -201,10 +201,10 @@ static int pending_call(struct notifier_block *self, unsigned long state, if (module != THIS_MODULE || state != MODULE_STATE_LIVE) return NOTIFY_DONE; - if (need_empress) - request_module("saa7134-empress"); - if (need_dvb) - request_module("saa7134-dvb"); + if (need_empress) + request_module("saa7134-empress"); + if (need_dvb) + request_module("saa7134-dvb"); return NOTIFY_DONE; } @@ -279,8 +279,8 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) { - __le32 *cpu; - dma_addr_t dma_addr; + __le32 *cpu; + dma_addr_t dma_addr; cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); if (NULL == cpu) @@ -440,7 +440,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ctrl |= SAA7134_MAIN_CTRL_TE0; irq |= SAA7134_IRQ1_INTE_RA0_1 | SAA7134_IRQ1_INTE_RA0_0; - cap = dev->video_q.curr->vb.field; + cap = dev->video_q.curr->vb.field; } /* video capture -- dma 1+2 (planar modes) */ @@ -646,7 +646,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); - init_MUTEX(&dev->lock); + init_MUTEX(&dev->lock); spin_lock_init(&dev->slock); saa7134_track_gpio(dev,"pre-init"); @@ -704,7 +704,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) saa7134_tvaudio_init2(dev); /* enable IRQ's */ - irq2_mask = + irq2_mask = SAA7134_IRQ2_INTE_DEC3 | SAA7134_IRQ2_INTE_DEC2 | SAA7134_IRQ2_INTE_DEC1 | @@ -889,8 +889,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); @@ -914,7 +914,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, dev->board, card[dev->nr] == dev->board ? @@ -964,12 +964,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, request_module("tuner"); if (dev->tda9887_conf) request_module("tda9887"); - if (card_is_empress(dev)) { + if (card_is_empress(dev)) { request_module("saa6752hs"); request_module_depend("saa7134-empress",&need_empress); } - if (card_is_dvb(dev)) + if (card_is_dvb(dev)) request_module_depend("saa7134-dvb",&need_dvb); v4l2_prio_init(&dev->prio); @@ -1078,7 +1078,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, static void __devexit saa7134_finidev(struct pci_dev *pci_dev) { - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct saa7134_dev *dev = pci_get_drvdata(pci_dev); struct list_head *item; struct saa7134_mpeg_ops *mops; @@ -1173,10 +1173,10 @@ EXPORT_SYMBOL(saa7134_ts_unregister); /* ----------------------------------------------------------- */ static struct pci_driver saa7134_pci_driver = { - .name = "saa7134", - .id_table = saa7134_pci_tbl, - .probe = saa7134_initdev, - .remove = __devexit_p(saa7134_finidev), + .name = "saa7134", + .id_table = saa7134_pci_tbl, + .probe = saa7134_initdev, + .remove = __devexit_p(saa7134_finidev), }; static int saa7134_init(void) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 87641f7e4322..5aadd44c2fa2 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -547,7 +547,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ u8 tuner_buf[14]; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; + .len = sizeof(tuner_buf) }; int i, tuner_freq, if_freq; u32 N; switch (params->u.ofdm.bandwidth) { @@ -606,7 +606,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; + .len = sizeof(tda827x_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 77b627eb6483..e9ec69efb4c9 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -55,7 +55,7 @@ static void ts_reset_encoder(struct saa7134_dev* dev) saa_writeb(SAA7134_SPECIAL_MODE, 0x00); msleep(10); - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); msleep(100); dev->empress_started = 0; } @@ -65,7 +65,7 @@ static int ts_init_encoder(struct saa7134_dev* dev) ts_reset_encoder(dev); saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); dev->empress_started = 1; - return 0; + return 0; } /* ------------------------------------------------------------------ */ @@ -169,7 +169,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 711aa8e85fac..2577d03485b8 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -239,7 +239,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, unsigned char data; int addr,rc,i,byte; - status = i2c_get_status(dev); + status = i2c_get_status(dev); if (!i2c_is_idle(status)) if (!i2c_reset(dev)) return -EIO; @@ -296,7 +296,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, rc = -EIO; if (!i2c_is_busy_wait(dev)) goto err; - status = i2c_get_status(dev); + status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; /* ensure that the bus is idle for at least one bit slot */ @@ -348,12 +348,12 @@ static int attach_inform(struct i2c_client *client) client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } if (tuner != UNSET) { - tun_setup.type = tuner; - tun_setup.addr = saa7134_boards[dev->board].tuner_addr; + tun_setup.type = tuner; + tun_setup.addr = saa7134_boards[dev->board].tuner_addr; if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) { @@ -361,11 +361,11 @@ static int attach_inform(struct i2c_client *client) client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } client->driver->command(client, TDA9887_SET_CONFIG, &conf); - return 0; + return 0; } static struct i2c_algorithm saa7134_algo = { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 9dc41c1427a8..7ce0459989b5 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -114,24 +114,24 @@ static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { /* Alfons Geser * updates from Job D. R. Borges */ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { - [ 18 ] = KEY_POWER, - [ 1 ] = KEY_TV, // DVR - [ 21 ] = KEY_DVD, // DVD - [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 27 ] = KEY_MUTE, // mute - [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 22 ] = KEY_ZOOM, // full screen - [ 28 ] = KEY_VIDEO, // video source / eject / delall - [ 29 ] = KEY_RESTART, // playback / angle / del - [ 47 ] = KEY_SEARCH, // scan / menu / playlist - [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 49 ] = KEY_HELP, // help - [ 50 ] = KEY_MODE, // num/memo - [ 51 ] = KEY_ESC, // cancel + [ 18 ] = KEY_POWER, + [ 1 ] = KEY_TV, // DVR + [ 21 ] = KEY_DVD, // DVD + [ 23 ] = KEY_AUDIO, // music + // DVR mode / DVD mode / music mode + + [ 27 ] = KEY_MUTE, // mute + [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek + [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek + [ 22 ] = KEY_ZOOM, // full screen + [ 28 ] = KEY_VIDEO, // video source / eject / delall + [ 29 ] = KEY_RESTART, // playback / angle / del + [ 47 ] = KEY_SEARCH, // scan / menu / playlist + [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo + + [ 49 ] = KEY_HELP, // help + [ 50 ] = KEY_MODE, // num/memo + [ 51 ] = KEY_ESC, // cancel [ 12 ] = KEY_UP, // up [ 16 ] = KEY_DOWN, // down @@ -148,24 +148,24 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 45 ] = KEY_PLAY, // play [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle - [ 0 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 42 ] = KEY_VOLUMEUP, - [ 17 ] = KEY_VOLUMEDOWN, - [ 24 ] = KEY_CHANNELUP, // CH.tracking up - [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down - - [ 19 ] = KEY_KPENTER, // enter - [ 33 ] = KEY_KPDOT, // . (decimal dot) + [ 0 ] = KEY_KP0, + [ 5 ] = KEY_KP1, + [ 6 ] = KEY_KP2, + [ 7 ] = KEY_KP3, + [ 9 ] = KEY_KP4, + [ 10 ] = KEY_KP5, + [ 11 ] = KEY_KP6, + [ 13 ] = KEY_KP7, + [ 14 ] = KEY_KP8, + [ 15 ] = KEY_KP9, + + [ 42 ] = KEY_VOLUMEUP, + [ 17 ] = KEY_VOLUMEDOWN, + [ 24 ] = KEY_CHANNELUP, // CH.tracking up + [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down + + [ 19 ] = KEY_KPENTER, // enter + [ 33 ] = KEY_KPDOT, // . (decimal dot) }; static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { @@ -455,13 +455,13 @@ static int build_key(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); - if (ir->polling) { - if (ir->last_gpio == gpio) - return 0; - ir->last_gpio = gpio; - } + if (ir->polling) { + if (ir->last_gpio == gpio) + return 0; + ir->last_gpio = gpio; + } - data = ir_extract_bits(gpio, ir->mask_keycode); + data = ir_extract_bits(gpio, ir->mask_keycode); dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", gpio, ir->mask_keycode, data); @@ -478,9 +478,9 @@ static int build_key(struct saa7134_dev *dev) void saa7134_input_irq(struct saa7134_dev *dev) { - struct saa7134_ir *ir = dev->remote; + struct saa7134_ir *ir = dev->remote; - if (!ir->polling) + if (!ir->polling) build_key(dev); } @@ -515,7 +515,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: - case SAA7134_BOARD_FLYTVPLATINUM_FM: + case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: ir_codes = flyvideo_codes; mask_keycode = 0xEC00000; @@ -557,7 +557,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; - case SAA7134_BOARD_KWORLD_TERMINATOR: + case SAA7134_BOARD_KWORLD_TERMINATOR: ir_codes = avacssmart_codes; mask_keycode = 0x00001f; mask_keyup = 0x000060; @@ -571,7 +571,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x004000; polling = 50; // ms break; - case SAA7134_BOARD_GOTVIEW_7135: + case SAA7134_BOARD_GOTVIEW_7135: ir_codes = gotview7135_codes; mask_keycode = 0x0003EC; mask_keyup = 0x008000; @@ -585,8 +585,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x400000; polling = 50; // ms break; - case SAA7134_BOARD_VIDEOMATE_DVBT_300: - case SAA7134_BOARD_VIDEOMATE_DVBT_200: + case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_VIDEOMATE_DVBT_200: ir_codes = videomate_tv_pvr_codes; mask_keycode = 0x003F00; mask_keyup = 0x040000; @@ -610,7 +610,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keycode = mask_keycode; ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; - ir->polling = polling; + ir->polling = polling; /* init input device */ snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index b1dcb4d10788..f1b0e0d93d7b 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -64,7 +64,7 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) dev->oss.bufsize = blksize * blocks; dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", - blocks,blksize,blksize * blocks / 1024); + blocks,blksize,blksize * blocks / 1024); return 0; } @@ -371,20 +371,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, p); - case SNDCTL_DSP_GETCAPS: + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); + case SNDCTL_DSP_GETCAPS: return 0; - case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_SPEED: if (get_user(val, p)) return -EFAULT; /* fall through */ - case SOUND_PCM_READ_RATE: + case SOUND_PCM_READ_RATE: return put_user(dev->oss.rate, p); - case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_STEREO: if (get_user(val, p)) return -EFAULT; down(&dev->oss.lock); @@ -396,7 +396,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, up(&dev->oss.lock); return put_user(dev->oss.channels-1, p); - case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_CHANNELS: if (get_user(val, p)) return -EFAULT; if (val != 1 && val != 2) @@ -409,15 +409,15 @@ static int dsp_ioctl(struct inode *inode, struct file *file, } up(&dev->oss.lock); /* fall through */ - case SOUND_PCM_READ_CHANNELS: + case SOUND_PCM_READ_CHANNELS: return put_user(dev->oss.channels, p); - case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE | AFMT_S16_LE | AFMT_S16_BE, p); - case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ if (get_user(val, p)) return -EFAULT; switch (val) { @@ -442,7 +442,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EINVAL; } - case SOUND_PCM_READ_BITS: + case SOUND_PCM_READ_BITS: switch (dev->oss.afmt) { case AFMT_U8: case AFMT_S8: @@ -456,20 +456,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EINVAL; } - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; - case SNDCTL_DSP_RESET: + case SNDCTL_DSP_RESET: down(&dev->oss.lock); if (dev->oss.recording_on) dsp_rec_stop(dev); up(&dev->oss.lock); return 0; - case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_GETBLKSIZE: return put_user(dev->oss.blksize, p); - case SNDCTL_DSP_SETFRAGMENT: + case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, p)) return -EFAULT; if (dev->oss.recording_on) @@ -480,7 +480,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, dsp_buffer_init(dev); return 0; - case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_SYNC: /* NOP */ return 0; @@ -563,7 +563,7 @@ mixer_recsrc_7133(struct saa7134_dev *dev) switch (dev->oss.input) { case TV: xbarin = 0; // Demodulator - anabar = 2; // DACs + anabar = 2; // DACs break; case LINE1: anabar = 0; // aux1, aux1 @@ -667,28 +667,28 @@ static int mixer_ioctl(struct inode *inode, struct file *file, if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, p); + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); case SOUND_MIXER_INFO: { mixer_info info; memset(&info,0,sizeof(info)); - strlcpy(info.id, "TV audio", sizeof(info.id)); - strlcpy(info.name, dev->name, sizeof(info.name)); - info.modify_counter = dev->oss.count; - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; + strlcpy(info.id, "TV audio", sizeof(info.id)); + strlcpy(info.name, dev->name, sizeof(info.name)); + info.modify_counter = dev->oss.count; + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; return 0; } case SOUND_OLD_MIXER_INFO: { _old_mixer_info info; memset(&info,0,sizeof(info)); - strlcpy(info.id, "TV audio", sizeof(info.id)); - strlcpy(info.name, dev->name, sizeof(info.name)); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; + strlcpy(info.id, "TV audio", sizeof(info.id)); + strlcpy(info.name, dev->name, sizeof(info.name)); + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; return 0; } case MIXER_READ(SOUND_MIXER_CAPS): @@ -771,7 +771,7 @@ struct file_operations saa7134_mixer_fops = { int saa7134_oss_init1(struct saa7134_dev *dev) { /* general */ - init_MUTEX(&dev->oss.lock); + init_MUTEX(&dev->oss.lock); init_waitqueue_head(&dev->oss.wq); switch (dev->pci->device) { diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index 58c521fade85..ac6431ba4fc3 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -27,7 +27,7 @@ /* DMA channels, n = 0 ... 6 */ #define SAA7134_RS_BA1(n) ((0x200 >> 2) + 4*n) -#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n) +#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n) #define SAA7134_RS_PITCH(n) ((0x208 >> 2) + 4*n) #define SAA7134_RS_CONTROL(n) ((0x20c >> 2) + 4*n) #define SAA7134_RS_CONTROL_WSWAP (0x01 << 25) @@ -53,14 +53,14 @@ /* main control */ #define SAA7134_MAIN_CTRL (0x2a8 >> 2) -#define SAA7134_MAIN_CTRL_VPLLE (1 << 15) -#define SAA7134_MAIN_CTRL_APLLE (1 << 14) -#define SAA7134_MAIN_CTRL_EXOSC (1 << 13) -#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12) -#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11) -#define SAA7134_MAIN_CTRL_ESFE (1 << 10) -#define SAA7134_MAIN_CTRL_EBADC (1 << 9) -#define SAA7134_MAIN_CTRL_EBDAC (1 << 8) +#define SAA7134_MAIN_CTRL_VPLLE (1 << 15) +#define SAA7134_MAIN_CTRL_APLLE (1 << 14) +#define SAA7134_MAIN_CTRL_EXOSC (1 << 13) +#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12) +#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11) +#define SAA7134_MAIN_CTRL_ESFE (1 << 10) +#define SAA7134_MAIN_CTRL_EBADC (1 << 9) +#define SAA7134_MAIN_CTRL_EBDAC (1 << 8) #define SAA7134_MAIN_CTRL_TE6 (1 << 6) #define SAA7134_MAIN_CTRL_TE5 (1 << 5) #define SAA7134_MAIN_CTRL_TE4 (1 << 4) diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index cdfd69873ba9..470903e2f5e5 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -111,8 +111,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, /* dma: setup channel 5 (= TS) */ control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (buf->pt->dma >> 12); + SAA7134_RS_CONTROL_ME | + (buf->pt->dma >> 12); saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index fdca6c563b96..3daf1b597958 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -246,7 +246,7 @@ static void mute_input_7134(struct saa7134_dev *dev) if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) /* 7134 mute */ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? - SAA7134_MUTE_MASK | + SAA7134_MUTE_MASK | SAA7134_MUTE_ANALOG | SAA7134_MUTE_I2S : SAA7134_MUTE_MASK); @@ -761,17 +761,17 @@ static int mute_input_7133(struct saa7134_dev *dev) /* switch gpio-connected external audio mux */ - if (0 != card(dev).gpiomask) { - mask = card(dev).gpiomask; + if (0 != card(dev).gpiomask) { + mask = card(dev).gpiomask; if (card(dev).mute.name && dev->ctl_mute) in = &card(dev).mute; else in = dev->input; - saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); - saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); + saa7134_track_gpio(dev,in->name); } return 0; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index cd5545b2d60b..86db7fb96efd 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -310,12 +310,12 @@ static struct saa7134_tvnorm tvnorms[] = { .h_start = 0, .h_stop = 719, - .video_v_start = 23, - .video_v_stop = 262, - .vbi_v_start_0 = 10, - .vbi_v_stop_0 = 21, - .vbi_v_start_1 = 273, - .src_timing = 7, + .video_v_start = 23, + .video_v_stop = 262, + .vbi_v_start_0 = 10, + .vbi_v_stop_0 = 21, + .vbi_v_start_1 = 273, + .src_timing = 7, .sync_control = 0x18, .luma_control = 0x40, @@ -659,7 +659,7 @@ static void set_size(struct saa7134_dev *dev, int task, prescale = 1; xscale = 1024 * dev->crop_current.width / prescale / width; yscale = 512 * div * dev->crop_current.height / height; - dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); + dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); set_h_prescale(dev,task,prescale); saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff); saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8); @@ -789,20 +789,20 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) maxh = dev->crop_current.height; if (V4L2_FIELD_ANY == field) { - field = (win->w.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; - } - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: - return -EINVAL; - } + field = (win->w.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; + } + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } win->field = field; if (win->w.width > maxw) @@ -1343,13 +1343,13 @@ video_poll(struct file *file, struct poll_table_struct *wait) if (res_locked(fh->dev,RESOURCE_VIDEO)) { up(&fh->cap.lock); return POLLERR; - } - if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); - return POLLERR; - } - fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); - fh->cap.read_off = 0; + } + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { + up(&fh->cap.lock); + return POLLERR; + } + fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); + fh->cap.read_off = 0; } up(&fh->cap.lock); buf = fh->cap.read_buf; @@ -1706,7 +1706,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, unsigned int tuner_type = dev->tuner_type; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -1934,26 +1934,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } case VIDIOC_S_AUDIO: return 0; - case VIDIOC_G_PARM: - { - struct v4l2_captureparm *parm = arg; - memset(parm,0,sizeof(*parm)); - return 0; - } - - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; - - *p = v4l2_prio_max(&dev->prio); - return 0; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *prio = arg; - - return v4l2_prio_change(&dev->prio, &fh->prio, *prio); - } + case VIDIOC_G_PARM: + { + struct v4l2_captureparm *parm = arg; + memset(parm,0,sizeof(*parm)); + return 0; + } + + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *p = arg; + + *p = v4l2_prio_max(&dev->prio); + return 0; + } + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *prio = arg; + + return v4l2_prio_change(&dev->prio, &fh->prio, *prio); + } /* --- preview ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: @@ -2102,7 +2102,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { int res = saa7134_resource(fh); - if (!res_get(dev,fh,res)) + if (!res_get(dev,fh,res)) return -EBUSY; return videobuf_streamon(saa7134_queue(fh)); } @@ -2144,7 +2144,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -2275,7 +2275,7 @@ struct video_device saa7134_video_template = { .name = "saa7134-video", .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = 0, .fops = &video_fops, .minor = -1, @@ -2322,7 +2322,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->tda9887_conf |= TDA9887_AUTOMUTE; dev->automute = 0; - INIT_LIST_HEAD(&dev->video_q.queue); + INIT_LIST_HEAD(&dev->video_q.queue); init_timer(&dev->video_q.timeout); dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 99bbdcf727c3..064c2f7a8c12 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -346,7 +346,7 @@ struct saa7134_fh { /* oss dsp status */ struct saa7134_oss { - struct semaphore lock; + struct semaphore lock; int minor_mixer; int minor_dsp; unsigned int users_dsp; @@ -384,9 +384,9 @@ struct saa7134_ir { u32 mask_keycode; u32 mask_keydown; u32 mask_keyup; - int polling; - u32 last_gpio; - struct timer_list timer; + int polling; + u32 last_gpio; + struct timer_list timer; }; /* ts/mpeg status */ @@ -409,8 +409,8 @@ struct saa7134_mpeg_ops { /* global device status */ struct saa7134_dev { struct list_head devlist; - struct semaphore lock; - spinlock_t slock; + struct semaphore lock; + spinlock_t slock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 255b6088ebf9..14cf1d357c3b 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -310,9 +310,9 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) memset(t,0,sizeof *t); client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; i2c_set_clientdata(client, t); do_tda7432_init(client); @@ -472,7 +472,7 @@ static int tda7432_command(struct i2c_client *client, } } - t->muted=(va->flags & VIDEO_AUDIO_MUTE); + t->muted=(va->flags & VIDEO_AUDIO_MUTE); if (t->muted) { /* Mute & update balance*/ @@ -503,12 +503,12 @@ static int tda7432_command(struct i2c_client *client, static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c tda7432 driver", + .name = "i2c tda7432 driver", .id = I2C_DRIVERID_TDA7432, - .flags = I2C_DF_NOTIFY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tda7432_probe, - .detach_client = tda7432_detach, - .command = tda7432_command, + .detach_client = tda7432_detach, + .command = tda7432_command, }; static struct i2c_client client_template = diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 1e2acc4abbe6..e2027dada5d1 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -48,7 +48,7 @@ static struct freq_entry div_table[] = { { 0x1C34, 3 }, { 0x0D34, 2 }, { 0x067B, 1 }, - { 0x0000, 0 }, + { 0x0000, 0 }, }; static struct freq_entry agc_table[] = { diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 7e3dcdb262b0..5a9faefc3640 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -126,20 +126,20 @@ static int tda9875_write(struct i2c_client *client, int subaddr, unsigned char v static int i2c_read_register(struct i2c_adapter *adap, int addr, int reg) { - unsigned char write[1]; - unsigned char read[1]; - struct i2c_msg msgs[2] = { - { addr, 0, 1, write }, - { addr, I2C_M_RD, 1, read } - }; - write[0] = reg; - - if (2 != i2c_transfer(adap,msgs,2)) { - printk(KERN_WARNING "tda9875: I/O error (read2)\n"); - return -1; - } - dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); - return read[0]; + unsigned char write[1]; + unsigned char read[1]; + struct i2c_msg msgs[2] = { + { addr, 0, 1, write }, + { addr, I2C_M_RD, 1, read } + }; + write[0] = reg; + + if (2 != i2c_transfer(adap,msgs,2)) { + printk(KERN_WARNING "tda9875: I/O error (read2)\n"); + return -1; + } + dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); + return read[0]; } static void tda9875_set(struct i2c_client *client) @@ -184,7 +184,7 @@ static void do_tda9875_init(struct i2c_client *client) tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ - tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ + tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ @@ -200,7 +200,7 @@ static void do_tda9875_init(struct i2c_client *client) t->mode=AUDIO_UNMUTE; t->lvol=t->rvol =0; /* 0dB */ - t->bass=0; /* 0dB */ + t->bass=0; /* 0dB */ t->treble=0; /* 0dB */ tda9875_set(client); @@ -239,9 +239,9 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind) memset(t,0,sizeof *t); client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; i2c_set_clientdata(client, t); if(!tda9875_checkit(adap,addr)) { @@ -287,7 +287,7 @@ static int tda9875_command(struct i2c_client *client, dprintk("In tda9875_command...\n"); switch (cmd) { - /* --- v4l ioctls --- */ + /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ case VIDIOCGAUDIO: @@ -355,7 +355,7 @@ static int tda9875_command(struct i2c_client *client, //printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); - tda9875_set(client); + tda9875_set(client); break; @@ -374,18 +374,18 @@ static int tda9875_command(struct i2c_client *client, static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c tda9875 driver", - .id = I2C_DRIVERID_TDA9875, - .flags = I2C_DF_NOTIFY, + .name = "i2c tda9875 driver", + .id = I2C_DRIVERID_TDA9875, + .flags = I2C_DF_NOTIFY, .attach_adapter = tda9875_probe, - .detach_client = tda9875_detach, - .command = tda9875_command, + .detach_client = tda9875_detach, + .command = tda9875_command, }; static struct i2c_client client_template = { - .name = "tda9875", - .driver = &driver, + .name = "tda9875", + .driver = &driver, }; static int __init tda9875_init(void) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 6d2914f738f2..9d6b6f57abcd 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -46,11 +46,11 @@ MODULE_LICENSE("GPL"); #define UNSET (-1U) #define tda9887_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) struct tda9887 { struct i2c_client client; @@ -484,11 +484,11 @@ static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) } } if (t->std & V4L2_STD_525_60) { - if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { + if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { bCarrierMode = cQSS; - } + } } if (bCarrierMode != UNSET) { @@ -568,8 +568,8 @@ static int tda9887_status(struct tda9887 *t) int rc; memset(buf,0,sizeof(buf)); - if (1 != (rc = i2c_master_recv(&t->client,buf,1))) - tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); + if (1 != (rc = i2c_master_recv(&t->client,buf,1))) + tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); dump_read_message(t, buf); return 0; } @@ -600,8 +600,8 @@ static int tda9887_configure(struct tda9887 *t) if (debug > 1) dump_write_message(t, t->data); - if (4 != (rc = i2c_master_send(&t->client,t->data,4))) - tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); + if (4 != (rc = i2c_master_send(&t->client,t->data,4))) + tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { msleep_interruptible(1000); @@ -616,11 +616,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) { struct tda9887 *t; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; @@ -628,7 +628,7 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) t->pinnacle_id = UNSET; t->radio_mode = V4L2_TUNER_MODE_STEREO; - tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); + tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -663,18 +663,18 @@ static int tda9887_detach(struct i2c_client *client) } #define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ - tda9887_info("switching to v4l2\n"); \ - t->using_v4l2 = 1; + tda9887_info("switching to v4l2\n"); \ + t->using_v4l2 = 1; #define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ tda9887_info("ignore v4l1 call\n"); \ - return 0; } + return 0; } static int tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tda9887 *t = i2c_get_clientdata(client); - switch (cmd) { + switch (cmd) { /* --- configuration --- */ case AUDC_SET_RADIO: diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 38bf50943798..a9375ef05de1 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -117,10 +117,10 @@ #define TEA5767_RESERVED_MASK 0xff enum tea5767_xtal_freq { - TEA5767_LOW_LO_32768 = 0, - TEA5767_HIGH_LO_32768 = 1, - TEA5767_LOW_LO_13MHz = 2, - TEA5767_HIGH_LO_13MHz = 3, + TEA5767_LOW_LO_32768 = 0, + TEA5767_HIGH_LO_32768 = 1, + TEA5767_LOW_LO_13MHz = 2, + TEA5767_HIGH_LO_13MHz = 3, }; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 44fa1423c1a9..e677869afcf3 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -432,23 +432,23 @@ static int tuner_detach(struct i2c_client *client) static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) { - if (mode == t->mode) - return 0; - - t->mode = mode; - - if (check_mode(t, cmd) == EINVAL) { - t->mode = T_STANDBY; - if (t->standby) - t->standby (client); - return EINVAL; - } - return 0; + if (mode == t->mode) + return 0; + + t->mode = mode; + + if (check_mode(t, cmd) == EINVAL) { + t->mode = T_STANDBY; + if (t->standby) + t->standby (client); + return EINVAL; + } + return 0; } #define switch_v4l2() if (!t->using_v4l2) \ - tuner_dbg("switching to v4l2\n"); \ - t->using_v4l2 = 1; + tuner_dbg("switching to v4l2\n"); \ + t->using_v4l2 = 1; static inline int check_v4l2(struct tuner *t) { @@ -623,7 +623,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); if (V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) { - if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") + if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") == EINVAL) return 0; } diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index e67d9e77c755..84338f1e3038 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -102,7 +102,7 @@ struct tunertype */ static struct tunertype tuners[] = { /* 0-9 */ - { "Temic PAL (4002 FH5)", TEMIC, PAL, + { "Temic PAL (4002 FH5)", TEMIC, PAL, 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623}, { "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I, 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, @@ -118,41 +118,41 @@ static struct tunertype tuners[] = { 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, { "Temic PAL_I (4062 FY5)", TEMIC, PAL_I, 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, - { "Temic NTSC (4036 FY5)", TEMIC, NTSC, + { "Temic NTSC (4036 FY5)", TEMIC, NTSC, 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, - { "Alps HSBH1", TEMIC, NTSC, + { "Alps HSBH1", TEMIC, NTSC, 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, /* 10-19 */ - { "Alps TSBE1", TEMIC, PAL, + { "Alps TSBE1", TEMIC, PAL, 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, - { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ + { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632}, - { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ + { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, - { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ + { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, { "Temic PAL_BG (4006FH5)", TEMIC, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, - { "Alps TSCH6", Alps, NTSC, - 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, - { "Temic PAL_DK (4016 FY5)", TEMIC, PAL, - 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, - { "Philips NTSC_M (MK2)", Philips, NTSC, - 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, - { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Alps TSCH6", Alps, NTSC, + 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, + { "Temic PAL_DK (4016 FY5)", TEMIC, PAL, + 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, + { "Philips NTSC_M (MK2)", Philips, NTSC, + 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, + { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, /* 20-29 */ - { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, - 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, - { "Temic NTSC (4039 FR5)", TEMIC, NTSC, - 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, - { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, - { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, + { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, + 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, + { "Temic NTSC (4039 FR5)", TEMIC, NTSC, + 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, + { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, { "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, @@ -173,21 +173,21 @@ static struct tunertype tuners[] = { { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */ 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 }, { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */ - 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, + 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, { "MT20xx universal", Microtune, PAL|NTSC, /* see mt20xx.c for details */ }, { "Temic PAL_BG (4106 FH5)", TEMIC, PAL, - 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, + 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL, - 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, + 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, { "Temic NTSC (4136 FY5)", TEMIC, NTSC, - 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, - { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, + 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, + { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL, 16*158.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, /* 40-49 */ { "HITACHI V7-J180AT", HITACHI, NTSC, @@ -196,24 +196,24 @@ static struct tunertype tuners[] = { 16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623}, { "Philips 1236D ATSC/NTSC daul in", Philips, ATSC, 16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, - { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, { "Microtune 4049 FM5", Microtune, PAL, 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC, 16*160.00,16*454.00,0x01,0x02,0x08,0xce,940}, - { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, - { "Tenna TNF 8831 BGFF)", Philips, PAL, - 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, + { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, + { "Tenna TNF 8831 BGFF)", Philips, PAL, + 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC, 16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732}, /* 50-59 */ - { "TCL 2002N", TCL, NTSC, - 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, + { "TCL 2002N", TCL, NTSC, + 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC, @@ -223,7 +223,7 @@ static struct tunertype tuners[] = { { "tda8290+75", Philips, PAL|NTSC, /* see tda8290.c for details */ }, { "TCL 2002MB", TCL, PAL, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, { "Philips FQ1236A MK4", Philips, NTSC, @@ -237,16 +237,16 @@ static struct tunertype tuners[] = { { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, + 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, { "Philips TEA5767HN FM Radio", Philips, RADIO, - /* see tea5767.c for details */}, + /* see tea5767.c for details */}, { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC, 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, { "Ymec TVF66T5-B/DFF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, - { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, + 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, + { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, { "Philips TD1316 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, @@ -281,7 +281,7 @@ static int tuner_stereo(struct i2c_client *c) status = tuner_getstatus (c); switch (t->type) { - case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FM1256_IH3: stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); @@ -302,7 +302,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) u8 config; u16 div; struct tunertype *tun; - unsigned char buffer[4]; + unsigned char buffer[4]; int rc; tun = &tuners[t->type]; @@ -419,7 +419,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); - if (4 != (rc = i2c_master_send(c,buffer,4))) + if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); if (t->type == TUNER_MICROTUNE_4042FI5) { @@ -458,7 +458,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tunertype *tun; struct tuner *t = i2c_get_clientdata(c); - unsigned char buffer[4]; + unsigned char buffer[4]; unsigned div; int rc; @@ -491,13 +491,13 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) buffer[3] = 0xa4; break; } - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); - if (4 != (rc = i2c_master_send(c,buffer,4))) + if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); } diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 1c31ef52f863..e1639a24f77f 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -458,8 +458,8 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) #define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ #define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ + * of line in and line out, only the + * interesting ones are defined */ #define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ #define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ @@ -1028,7 +1028,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6300_TR 0x03 /* treble */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6300_S_SA 0x01 /* stereo A input */ #define TEA6300_S_SB 0x02 /* stereo B */ #define TEA6300_S_SC 0x04 /* stereo C */ @@ -1042,7 +1042,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6320_BA 0x05 /* bass (0-4) */ #define TEA6320_TR 0x06 /* treble (0-4) */ #define TEA6320_S 0x07 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6320_S_SA 0x07 /* stereo A input */ #define TEA6320_S_SB 0x06 /* stereo B */ #define TEA6320_S_SC 0x05 /* stereo C */ @@ -1082,7 +1082,7 @@ static int tea6320_initialize(struct CHIPSTATE * chip) #define TDA8425_BA 0x02 /* bass */ #define TDA8425_TR 0x03 /* treble */ #define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ + /* values for those registers: */ #define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ #define TDA8425_S1_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */ #define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */ @@ -1148,7 +1148,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) /* bit definition of the RESET register, I2C data. */ #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ - /* code of remote controller */ + /* code of remote controller */ #define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ #define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ #define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ @@ -1281,7 +1281,7 @@ static struct CHIPDESC chiplist[] = { .setmode = tda9840_setmode, .checkmode = generic_checkmode, - .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN + .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN /* ,TDA9840_SW, TDA9840_MONO */} } }, { @@ -1467,7 +1467,7 @@ static struct CHIPDESC chiplist[] = { .setmode = ta8874z_setmode, .checkmode = generic_checkmode, - .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, + .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, }, { .name = NULL } /* EOF */ }; @@ -1486,8 +1486,8 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; memset(chip,0,sizeof(*chip)); memcpy(&chip->c,&client_template,sizeof(struct i2c_client)); - chip->c.adapter = adap; - chip->c.addr = addr; + chip->c.adapter = adap; + chip->c.addr = addr; i2c_set_clientdata(&chip->c, chip); /* find description for the chip */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index ee605712bf19..68128e04dacc 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -6,12 +6,12 @@ * which are: Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2001 Gerd Knorr * Adjustments to fit a more general model and all bugs: - Copyright (C) 2003 John Klar + Copyright (C) 2003 John Klar * 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 @@ -54,14 +54,14 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define tveeprom_info(fmt, arg...) do {\ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + c->adapter->nr, c->addr , ##arg); } while (0) #define tveeprom_warn(fmt, arg...) do {\ printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + c->adapter->nr, c->addr , ##arg); } while (0) #define tveeprom_dbg(fmt, arg...) do {\ if (debug) \ - printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ + c->adapter->nr, c->addr , ##arg); } while (0) /* ----------------------------------------------------------------------- */ @@ -294,7 +294,7 @@ static const char *decoderIC[] = { static int hasRadioTuner(int tunerType) { - switch (tunerType) { + switch (tunerType) { case 18: //PNPEnv_TUNER_FR1236_MK2: case 23: //PNPEnv_TUNER_FM1236: case 38: //PNPEnv_TUNER_FMR1236: @@ -326,12 +326,12 @@ static int hasRadioTuner(int tunerType) case 89: //PNPEnv_TUNER_TCL_MFPE05_2: case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: return 1; - } - return 0; + } + return 0; } void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index d86e08ebddfc..8318bd1aad00 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -79,7 +79,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm { struct video_audio va; int left,right,ret,val = 0; - struct TVMIXER *mix = file->private_data; + struct TVMIXER *mix = file->private_data; struct i2c_client *client = mix->dev; void __user *argp = (void __user *)arg; int __user *p = argp; @@ -87,25 +87,25 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm if (NULL == client) return -ENODEV; - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - strlcpy(info.id, "tv card", sizeof(info.id)); - strlcpy(info.name, client->name, sizeof(info.name)); - info.modify_counter = 42 /* FIXME */; - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - strlcpy(info.id, "tv card", sizeof(info.id)); - strlcpy(info.name, client->name, sizeof(info.name)); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, p); + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + strlcpy(info.id, "tv card", sizeof(info.id)); + strlcpy(info.name, client->name, sizeof(info.name)); + info.modify_counter = 42 /* FIXME */; + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == SOUND_OLD_MIXER_INFO) { + _old_mixer_info info; + strlcpy(info.id, "tv card", sizeof(info.id)); + strlcpy(info.name, client->name, sizeof(info.name)); + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == OSS_GETVERSION) + return put_user(SOUND_VERSION, p); if (_SIOC_DIR(cmd) & _SIOC_WRITE) if (get_user(val, p)) @@ -181,8 +181,8 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm static int tvmixer_open(struct inode *inode, struct file *file) { - int i, minor = iminor(inode); - struct TVMIXER *mix = NULL; + int i, minor = iminor(inode); + struct TVMIXER *mix = NULL; struct i2c_client *client = NULL; for (i = 0; i < DEV_MAX; i++) { @@ -204,7 +204,7 @@ static int tvmixer_open(struct inode *inode, struct file *file) #endif if (client->adapter->owner) try_module_get(client->adapter->owner); - return 0; + return 0; } static int tvmixer_release(struct inode *inode, struct file *file) @@ -231,15 +231,15 @@ static struct i2c_driver driver = { .owner = THIS_MODULE, #endif .name = "tv card mixer driver", - .id = I2C_DRIVERID_TVMIXER, + .id = I2C_DRIVERID_TVMIXER, #ifdef I2C_DF_DUMMY .flags = I2C_DF_DUMMY, #else .flags = I2C_DF_NOTIFY, - .detach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, #endif - .attach_adapter = tvmixer_adapters, - .detach_client = tvmixer_clients, + .attach_adapter = tvmixer_adapters, + .detach_client = tvmixer_clients, }; static struct file_operations tvmixer_fops = { diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 88beb5a3be15..4134549d11a8 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -960,7 +960,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt->start[1] = fmt2->fmt.vbi.start[1]; fmt->count[1] = fmt2->fmt.vbi.count[1]; fmt->flags = fmt2->fmt.vbi.flags & 0x03; - break; + break; } case VIDIOCSVBIFMT: { diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 574b8e36f3c6..acfd3a103f35 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -147,7 +147,7 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, data,size,dma->nr_pages); down_read(¤t->mm->mmap_sem); - err = get_user_pages(current,current->mm, + err = get_user_pages(current,current->mm, data & PAGE_MASK, dma->nr_pages, rw == READ, 1, /* force */ dma->pages, NULL); @@ -750,9 +750,9 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, { enum v4l2_field field; unsigned long flags; - int retval; + int retval; - /* setup stuff */ + /* setup stuff */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); if (NULL == q->read_buf) @@ -760,18 +760,18 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, q->read_buf->memory = V4L2_MEMORY_USERPTR; q->read_buf->baddr = (unsigned long)data; - q->read_buf->bsize = count; + q->read_buf->bsize = count; field = videobuf_next_field(q); retval = q->ops->buf_prepare(q,q->read_buf,field); if (0 != retval) goto done; - /* start capture & wait */ + /* start capture & wait */ spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); spin_unlock_irqrestore(q->irqlock,flags); - retval = videobuf_waiton(q->read_buf,0,0); - if (0 == retval) { + retval = videobuf_waiton(q->read_buf,0,0); + if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) retval = -EIO; @@ -828,7 +828,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* wait until capture is done */ - retval = videobuf_waiton(q->read_buf, nonblocking, 1); + retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); @@ -1096,7 +1096,7 @@ videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n", vaddr,vma->vm_start,vma->vm_end); - if (vaddr > vma->vm_end) + if (vaddr > vma->vm_end) return NOPAGE_SIGBUS; page = alloc_page(GFP_USER); if (!page) diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 8200f3dad0c6..5bd592673b94 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -36,10 +36,10 @@ MODULE_LICENSE("GPL"); #define wm8775_err(fmt, arg...) do { \ printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) #define wm8775_info(fmt, arg...) do { \ printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 1cc8c31b7988..22e6e4bad7b8 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -202,9 +202,9 @@ struct video_audio #define VIDEO_SOUND_STEREO 2 #define VIDEO_SOUND_LANG1 4 #define VIDEO_SOUND_LANG2 8 - __u16 mode; - __u16 balance; /* Stereo balance */ - __u16 step; /* Step actual volume uses */ + __u16 mode; + __u16 balance; /* Stereo balance */ + __u16 step; /* Step actual volume uses */ }; struct video_clip diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 27979003db44..a9a0999be702 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -24,7 +24,7 @@ /* Four-character-code (FOURCC) */ #define v4l2_fourcc(a,b,c,d)\ - (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) /* * E N U M S @@ -154,20 +154,20 @@ struct v4l2_capability }; /* Values for 'capabilities' field */ -#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ -#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ -#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ -#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ -#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ #if 1 #define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ #define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ #endif -#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ -#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ -#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ -#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ @@ -179,13 +179,13 @@ struct v4l2_capability struct v4l2_pix_format { - __u32 width; - __u32 height; - __u32 pixelformat; + __u32 width; + __u32 height; + __u32 pixelformat; enum v4l2_field field; __u32 bytesperline; /* for padding, zero if unused */ - __u32 sizeimage; - enum v4l2_colorspace colorspace; + __u32 sizeimage; + enum v4l2_colorspace colorspace; __u32 priv; /* private data, depends on pixelformat */ }; @@ -238,12 +238,12 @@ struct v4l2_pix_format */ struct v4l2_fmtdesc { - __u32 index; /* Format number */ + __u32 index; /* Format number */ enum v4l2_buf_type type; /* buffer type */ __u32 flags; - __u8 description[32]; /* Description string */ - __u32 pixelformat; /* Format fourcc */ - __u32 reserved[4]; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 @@ -393,7 +393,7 @@ struct v4l2_jpegcompression #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; @@ -402,10 +402,10 @@ struct v4l2_jpegcompression */ struct v4l2_requestbuffers { - __u32 count; + __u32 count; enum v4l2_buf_type type; enum v4l2_memory memory; - __u32 reserved[2]; + __u32 reserved[2]; }; struct v4l2_buffer @@ -511,9 +511,9 @@ struct v4l2_outputparm struct v4l2_cropcap { enum v4l2_buf_type type; - struct v4l2_rect bounds; - struct v4l2_rect defrect; - struct v4l2_fract pixelaspect; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; }; struct v4l2_crop { @@ -587,7 +587,7 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_Nc |\ V4L2_STD_SECAM) #define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ - V4L2_STD_ATSC_16_VSB) + V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL (V4L2_STD_525_60 |\ @@ -595,7 +595,7 @@ typedef __u64 v4l2_std_id; struct v4l2_standard { - __u32 index; + __u32 index; v4l2_std_id id; __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ @@ -610,9 +610,9 @@ struct v4l2_standard struct v4l2_input { __u32 index; /* Which input */ - __u8 name[32]; /* Label */ + __u8 name[32]; /* Label */ __u32 type; /* Type of input */ - __u32 audioset; /* Associated audios (bitfield) */ + __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ v4l2_std_id std; __u32 status; @@ -647,9 +647,9 @@ struct v4l2_input struct v4l2_output { __u32 index; /* Which output */ - __u8 name[32]; /* Label */ + __u8 name[32]; /* Label */ __u32 type; /* Type of output */ - __u32 audioset; /* Associated audios (bitfield) */ + __u32 audioset; /* Associated audios (bitfield) */ __u32 modulator; /* Associated modulator */ v4l2_std_id std; __u32 reserved[4]; @@ -671,12 +671,12 @@ struct v4l2_control /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ struct v4l2_queryctrl { - __u32 id; + __u32 id; enum v4l2_ctrl_type type; __u8 name[32]; /* Whatever */ __s32 minimum; /* Note signedness */ __s32 maximum; - __s32 step; + __s32 step; __s32 default_value; __u32 flags; __u32 reserved[2]; @@ -779,10 +779,10 @@ struct v4l2_modulator struct v4l2_frequency { - __u32 tuner; + __u32 tuner; enum v4l2_tuner_type type; - __u32 frequency; - __u32 reserved[8]; + __u32 frequency; + __u32 reserved[8]; }; /* @@ -846,14 +846,14 @@ struct v4l2_vbi_format struct v4l2_sliced_vbi_format { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 io_size; - __u32 reserved[2]; /* must be zero */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ }; #define V4L2_SLICED_TELETEXT_B (0x0001) @@ -866,22 +866,22 @@ struct v4l2_sliced_vbi_format struct v4l2_sliced_vbi_cap { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 reserved[4]; /* must be 0 */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 reserved[4]; /* must be 0 */ }; struct v4l2_sliced_vbi_data { - __u32 id; - __u32 field; /* 0: first field, 1: second field */ - __u32 line; /* 1-23 */ - __u32 reserved; /* must be 0 */ - __u8 data[48]; + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; }; #endif @@ -896,9 +896,9 @@ struct v4l2_format enum v4l2_buf_type type; union { - struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE - struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY - struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE + struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE + struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY + struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE #if 1 struct v4l2_sliced_vbi_format sliced; // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE #endif diff --git a/include/media/audiochip.h b/include/media/audiochip.h index dd1e484e86d3..b7d4b0930408 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -10,13 +10,13 @@ enum audiochip { /* Provided by video chip */ AUDIO_CHIP_INTERNAL, /* Provided by tvaudio.c */ - AUDIO_CHIP_TDA8425, - AUDIO_CHIP_TEA6300, - AUDIO_CHIP_TEA6420, - AUDIO_CHIP_TDA9840, - AUDIO_CHIP_TDA985X, - AUDIO_CHIP_TDA9874, - AUDIO_CHIP_PIC16C54, + AUDIO_CHIP_TDA8425, + AUDIO_CHIP_TEA6300, + AUDIO_CHIP_TEA6420, + AUDIO_CHIP_TDA9840, + AUDIO_CHIP_TDA985X, + AUDIO_CHIP_TDA9874, + AUDIO_CHIP_PIC16C54, /* Provided by msp3400.c */ AUDIO_CHIP_MSP34XX }; diff --git a/include/media/tuner.h b/include/media/tuner.h index 81025323267f..94a9511479a1 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -215,14 +215,14 @@ extern int tea5767_autodetection(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #endif /* __KERNEL__ */ diff --git a/include/media/video-buf.h b/include/media/video-buf.h index ae8d7a000440..ee8eb15c0ea6 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -177,7 +177,7 @@ struct videobuf_queue_ops { }; struct videobuf_queue { - struct semaphore lock; + struct semaphore lock; spinlock_t *irqlock; struct pci_dev *pci; -- cgit v1.2.3 From f2421ca3383ed35bc634aa29416a3229dc603fa4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:45 -0800 Subject: [PATCH] v4l: 801: whitespaces cleanups - Whitespaces Cleanups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/lifeview.txt | 6 +++--- drivers/media/video/bttv-cards.c | 4 ++-- drivers/media/video/bttv-risc.c | 4 ++-- drivers/media/video/cx88/cx88-core.c | 4 ++-- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/saa7134/saa7134-alsa.c | 12 ++++++------ drivers/media/video/saa7134/saa7134-dvb.c | 4 ++-- drivers/media/video/saa7134/saa7134-input.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 4 ++-- drivers/media/video/tvaudio.c | 8 ++++---- drivers/media/video/tveeprom.c | 2 +- include/linux/videodev2.h | 10 +++++----- 12 files changed, 31 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt index f66320bd7b67..05f9eb57aac9 100644 --- a/Documentation/video4linux/lifeview.txt +++ b/Documentation/video4linux/lifeview.txt @@ -28,9 +28,9 @@ saa7134: /* GP17 Strap "GP7"=High */ /* GP16 Strap "GP6"=High - 0=Radio 1=TV - Drives SA630D ENCH1 and HEF4052 A1 pins - to do FM radio through SIF input */ + 0=Radio 1=TV + Drives SA630D ENCH1 and HEF4052 A1 pins + to do FM radio through SIF input */ /* GP15 nc */ /* GP14 nc */ /* GP13 nc */ diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 92bb515fbe4d..695a67e9edd7 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -3585,7 +3585,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) for(i = 0; i<14; i++) checksum += ee[i+offset]; checksum = ~checksum; /* no idea why */ if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { + ((checksum & 0x0FF) == ee[offset+15])) { break; } } @@ -4420,7 +4420,7 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set) if (val) { gpio_bits(0x140000, val); if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); + bttv_gpio_tracking(btv,"windvr"); } } else { v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index 3028862934dd..b40e9734bf08 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -88,9 +88,9 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index f01a631d0c00..eb806af17182 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -166,9 +166,9 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| + *(rp++)=cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 3be601cfc99b..a7a077196fc9 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -128,7 +128,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) static u8 reset [] = { 0x50, 0x80 }; static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; + 0x00, 0xFF, 0x00, 0x40, 0x40 }; static u8 dntv_extra[] = { 0xB5, 0x7A }; static u8 capt_range_cfg[] = { 0x75, 0x32 }; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index e9ffe8f144ac..e7c3691fc500 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -277,7 +277,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) BUG(); videobuf_dma_init(&dev->oss.dma); err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); if (0 != err) return err; return 0; @@ -336,9 +336,9 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) goto fail1; if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, - 0))) + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) goto fail2; @@ -481,8 +481,8 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * static snd_pcm_hardware_t snd_card_saa7134_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5aadd44c2fa2..342891d431a8 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -547,7 +547,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ u8 tuner_buf[14]; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; + .len = sizeof(tuner_buf) }; int i, tuner_freq, if_freq; u32 N; switch (params->u.ofdm.bandwidth) { @@ -606,7 +606,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; + .len = sizeof(tda827x_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7ce0459989b5..f99dbb729555 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -118,7 +118,7 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 1 ] = KEY_TV, // DVR [ 21 ] = KEY_DVD, // DVD [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode + // DVR mode / DVD mode / music mode [ 27 ] = KEY_MUTE, // mute [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 86db7fb96efd..caeb47c68b8b 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1345,8 +1345,8 @@ video_poll(struct file *file, struct poll_table_struct *wait) return POLLERR; } if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); - return POLLERR; + up(&fh->cap.lock); + return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index e1639a24f77f..75901b030730 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1028,7 +1028,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6300_TR 0x03 /* treble */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6300_S_SA 0x01 /* stereo A input */ #define TEA6300_S_SB 0x02 /* stereo B */ #define TEA6300_S_SC 0x04 /* stereo C */ @@ -1042,7 +1042,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6320_BA 0x05 /* bass (0-4) */ #define TEA6320_TR 0x06 /* treble (0-4) */ #define TEA6320_S 0x07 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6320_S_SA 0x07 /* stereo A input */ #define TEA6320_S_SB 0x06 /* stereo B */ #define TEA6320_S_SC 0x05 /* stereo C */ @@ -1082,7 +1082,7 @@ static int tea6320_initialize(struct CHIPSTATE * chip) #define TDA8425_BA 0x02 /* bass */ #define TDA8425_TR 0x03 /* treble */ #define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ + /* values for those registers: */ #define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ #define TDA8425_S1_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */ #define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */ @@ -1148,7 +1148,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) /* bit definition of the RESET register, I2C data. */ #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ - /* code of remote controller */ + /* code of remote controller */ #define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ #define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ #define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 68128e04dacc..d83a33618119 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -331,7 +331,7 @@ static int hasRadioTuner(int tunerType) } void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a9a0999be702..090091560c36 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -393,7 +393,7 @@ struct v4l2_jpegcompression #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; @@ -849,8 +849,8 @@ struct v4l2_sliced_vbi_format __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 io_size; __u32 reserved[2]; /* must be zero */ @@ -869,8 +869,8 @@ struct v4l2_sliced_vbi_cap __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 reserved[4]; /* must be 0 */ }; -- cgit v1.2.3 From de48eebce8b63dbae7272ee80f4fe0eaddb61278 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:37:48 -0800 Subject: [PATCH] v4l: 806: add support for tda8275a - Add support for tda8275a Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 638 +++++++++++++++++++++++++++++---------- drivers/media/video/tuner-core.c | 2 +- include/media/tuner.h | 8 +- 3 files changed, 484 insertions(+), 164 deletions(-) (limited to 'include') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index e2027dada5d1..47d3d2ce9770 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -1,177 +1,402 @@ /* - * - * i2c tv tuner chip device driver - * controls the philips tda8290+75 tuner chip combo. - */ + + i2c tv tuner chip device driver + controls the philips tda8290+75 tuner chip combo. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include #include #include -#define I2C_ADDR_TDA8290 0x4b -#define I2C_ADDR_TDA8275 0x61 - /* ---------------------------------------------------------------------- */ -struct freq_entry { - u16 freq; - u8 value; +struct tda827x_data { + u32 lomax; + u8 spd; + u8 bs; + u8 bp; + u8 cp; + u8 gc3; + u8 div1p5; }; -static struct freq_entry band_table[] = { - { 0x2DF4, 0x1C }, - { 0x2574, 0x14 }, - { 0x22B4, 0x0C }, - { 0x20D4, 0x0B }, - { 0x1E74, 0x3B }, - { 0x1C34, 0x33 }, - { 0x16F4, 0x5B }, - { 0x1454, 0x53 }, - { 0x12D4, 0x52 }, - { 0x1034, 0x4A }, - { 0x0EE4, 0x7A }, - { 0x0D34, 0x72 }, - { 0x0B54, 0x9A }, - { 0x0914, 0x91 }, - { 0x07F4, 0x89 }, - { 0x0774, 0xB9 }, - { 0x067B, 0xB1 }, - { 0x0634, 0xD9 }, - { 0x05A4, 0xD8 }, // FM radio - { 0x0494, 0xD0 }, - { 0x03BC, 0xC8 }, - { 0x0394, 0xF8 }, // 57250000 Hz - { 0x0000, 0xF0 }, // 0 + /* Note lomax entry is lo / 62500 */ + +static struct tda827x_data tda827x_analog[] = { + { .lomax = 992, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 62 MHz */ + { .lomax = 1056, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 66 MHz */ + { .lomax = 1216, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 76 MHz */ + { .lomax = 1344, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 84 MHz */ + { .lomax = 1488, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 93 MHz */ + { .lomax = 1568, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 98 MHz */ + { .lomax = 1744, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 109 MHz */ + { .lomax = 1968, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 123 MHz */ + { .lomax = 2128, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 133 MHz */ + { .lomax = 2416, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 151 MHz */ + { .lomax = 2464, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 154 MHz */ + { .lomax = 2896, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 181 MHz */ + { .lomax = 2960, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 185 MHz */ + { .lomax = 3472, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 217 MHz */ + { .lomax = 3904, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 244 MHz */ + { .lomax = 4240, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 265 MHz */ + { .lomax = 4832, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 302 MHz */ + { .lomax = 5184, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 324 MHz */ + { .lomax = 5920, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 370 MHz */ + { .lomax = 7264, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 454 MHz */ + { .lomax = 7888, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 493 MHz */ + { .lomax = 8480, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 530 MHz */ + { .lomax = 8864, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 554 MHz */ + { .lomax = 9664, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 604 MHz */ + { .lomax = 11088, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 696 MHz */ + { .lomax = 11840, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 740 MHz */ + { .lomax = 13120, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 820 MHz */ + { .lomax = 13840, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 865 MHz */ + { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ }; -static struct freq_entry div_table[] = { - { 0x1C34, 3 }, - { 0x0D34, 2 }, - { 0x067B, 1 }, - { 0x0000, 0 }, -}; +static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) +{ + unsigned char tuner_reg[8]; + unsigned char reg2[2]; + u32 N; + int i; + struct tuner *t = i2c_get_clientdata(c); + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0}; -static struct freq_entry agc_table[] = { - { 0x22B4, 0x8F }, - { 0x0B54, 0x9F }, - { 0x09A4, 0x8F }, - { 0x0554, 0x9F }, - { 0x0000, 0xBF }, -}; + if (t->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; + + N = freq + ifc; + i = 0; + while (tda827x_analog[i].lomax < N) { + if(tda827x_analog[i + 1].lomax == 0) + break; + i++; + } + + N = N << tda827x_analog[i].spd; + + tuner_reg[0] = 0; + tuner_reg[1] = (unsigned char)(N>>8); + tuner_reg[2] = (unsigned char) N; + tuner_reg[3] = 0x40; + tuner_reg[4] = 0x52 + (t->tda827x_lpsel << 5); + tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + + (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; + tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); + tuner_reg[7] = 0x8f; + + msg.buf = tuner_reg; + msg.len = 8; + i2c_transfer(c->adapter, &msg, 1); + + msg.buf= reg2; + msg.len = 2; + reg2[0] = 0x80; + reg2[1] = 0; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x60; + reg2[1] = 0xbf; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x30; + reg2[1] = tuner_reg[4] + 0x80; + i2c_transfer(c->adapter, &msg, 1); + + msleep(1); + reg2[0] = 0x30; + reg2[1] = tuner_reg[4] + 4; + i2c_transfer(c->adapter, &msg, 1); + + msleep(1); + reg2[0] = 0x30; + reg2[1] = tuner_reg[4]; + i2c_transfer(c->adapter, &msg, 1); + + msleep(550); + reg2[0] = 0x30; + reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; + i2c_transfer(c->adapter, &msg, 1); -static __u8 get_freq_entry( struct freq_entry* table, __u16 freq) + reg2[0] = 0x60; + reg2[1] = 0x7f; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x80; + reg2[1] = 0x08; // Vsync en + i2c_transfer(c->adapter, &msg, 1); +} + +static void tda827x_agcf(struct i2c_client *c) { - while(table->freq && table->freq > freq) - table++; - return table->value; + struct tuner *t = i2c_get_clientdata(c); + unsigned char data[] = {0x80, 0x0c}; + struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data, + .flags = 0, .len = 2}; + i2c_transfer(c->adapter, &msg, 1); } /* ---------------------------------------------------------------------- */ -static unsigned char i2c_enable_bridge[2] = { 0x21, 0xC0 }; -static unsigned char i2c_disable_bridge[2] = { 0x21, 0x80 }; -static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00, - 0xfC, 0x04, 0xA3, 0x3F, - 0x2A, 0x04, 0xFF, 0x00, - 0x00, 0x40 }; -static unsigned char i2c_set_VS[2] = { 0x30, 0x6F }; -static unsigned char i2c_set_GP01_CF[2] = { 0x20, 0x0B }; -static unsigned char i2c_tda8290_reset[2] = { 0x00, 0x00 }; -static unsigned char i2c_tda8290_standby[2] = { 0x00, 0x02 }; -static unsigned char i2c_gainset_off[2] = { 0x28, 0x14 }; -static unsigned char i2c_gainset_on[2] = { 0x28, 0x54 }; -static unsigned char i2c_agc3_00[2] = { 0x80, 0x00 }; -static unsigned char i2c_agc2_BF[2] = { 0x60, 0xBF }; -static unsigned char i2c_cb1_D0[2] = { 0x30, 0xD0 }; -static unsigned char i2c_cb1_D2[2] = { 0x30, 0xD2 }; -static unsigned char i2c_cb1_56[2] = { 0x30, 0x56 }; -static unsigned char i2c_cb1_52[2] = { 0x30, 0x52 }; -static unsigned char i2c_cb1_50[2] = { 0x30, 0x50 }; -static unsigned char i2c_agc2_7F[2] = { 0x60, 0x7F }; -static unsigned char i2c_agc3_08[2] = { 0x80, 0x08 }; - -/* FIXME: European PAL/SECAM should select 9MHz Lowpass Filter, while - NTSC/M and PAL/M should be using 7MHz filter, by selecting CB3 */ -static unsigned char i2c_cb3_9MHz[2] = { 0xc0, 0x39 }; -static unsigned char i2c_cb3_7MHz[2] = { 0xc0, 0x3B }; - -static struct i2c_msg i2c_msg_init[] = { - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_init_tda8275), i2c_init_tda8275 }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_VS), i2c_set_VS }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_GP01_CF), i2c_set_GP01_CF }, +struct tda827xa_data { + u32 lomax; + u8 svco; + u8 spd; + u8 scr; + u8 sbs; + u8 gc3; }; -static struct i2c_msg i2c_msg_prolog[] = { -// { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_easy_mode), i2c_easy_mode }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_off), i2c_gainset_off }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_reset), i2c_tda8290_reset }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge }, +static struct tda827xa_data tda827xa_analog[] = { + { .lomax = 910, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, /* 56.875 MHz */ + { .lomax = 1076, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 67.25 MHz */ + { .lomax = 1300, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 81.25 MHz */ + { .lomax = 1560, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 97.5 MHz */ + { .lomax = 1820, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, /* 113.75 MHz */ + { .lomax = 2152, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 134.5 MHz */ + { .lomax = 2464, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 154 MHz */ + { .lomax = 2600, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 162.5 MHz */ + { .lomax = 2928, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 183 MHz */ + { .lomax = 3120, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, /* 195 MHz */ + { .lomax = 3640, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, /* 227.5 MHz */ + { .lomax = 4304, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, /* 269 MHz */ + { .lomax = 5200, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, /* 325 MHz */ + { .lomax = 6240, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 390 MHz */ + { .lomax = 7280, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 455 MHz */ + { .lomax = 8320, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 520 MHz */ + { .lomax = 8608, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, /* 538 MHz */ + { .lomax = 8864, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 554 MHz */ + { .lomax = 9920, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 620 MHz */ + { .lomax = 10400, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 650 MHz */ + { .lomax = 11200, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 700 MHz */ + { .lomax = 12480, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 780 MHz */ + { .lomax = 13120, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 820 MHz */ + { .lomax = 13920, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 870 MHz */ + { .lomax = 14576, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, /* 911 MHz */ + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ }; -static struct i2c_msg i2c_msg_config[] = { -// { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_set_freq), i2c_set_freq }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_00), i2c_agc3_00 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_BF), i2c_agc2_BF }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D2), i2c_cb1_D2 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_56), i2c_cb1_56 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_52), i2c_cb1_52 }, -}; +static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) +{ + unsigned char tuner_reg[14]; + unsigned char reg2[2]; + u32 N; + int i; + struct tuner *t = i2c_get_clientdata(c); + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0}; -static struct i2c_msg i2c_msg_epilog[] = { - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_50), i2c_cb1_50 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_7F), i2c_agc2_7F }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_08), i2c_agc3_08 }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on }, -}; + if (t->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; -static struct i2c_msg i2c_msg_standby[] = { - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D0), i2c_cb1_D0 }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_standby), i2c_tda8290_standby }, -}; + N = freq + ifc; + i = 0; + while (tda827xa_analog[i].lomax < N) { + if(tda827xa_analog[i + 1].lomax == 0) + break; + i++; + } + + N = N << tda827xa_analog[i].spd; + + tuner_reg[0] = 0; + tuner_reg[1] = (unsigned char)(N>>8); + tuner_reg[2] = (unsigned char) N; + tuner_reg[3] = 0; + tuner_reg[4] = 0x16; + tuner_reg[5] = (tda827xa_analog[i].spd << 5) + (tda827xa_analog[i].svco << 3) + + tda827xa_analog[i].sbs; + tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); + tuner_reg[7] = 0x0c; + tuner_reg[8] = 4; + tuner_reg[9] = 0x20; + tuner_reg[10] = 0xff; + tuner_reg[11] = 0xe0; + tuner_reg[12] = 0; + tuner_reg[13] = 0x39 + (t->tda827x_lpsel << 1); + + msg.buf = tuner_reg; + msg.len = 14; + i2c_transfer(c->adapter, &msg, 1); + + msg.buf= reg2; + msg.len = 2; + reg2[0] = 0x60; + reg2[1] = 0x3c; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0xa0; + reg2[1] = 0xc0; + i2c_transfer(c->adapter, &msg, 1); + + msleep(2); + reg2[0] = 0x30; + reg2[1] = 0x10 + tda827xa_analog[i].scr; + i2c_transfer(c->adapter, &msg, 1); + + msleep(550); + reg2[0] = 0x50; + reg2[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x80; + reg2[1] = 0x28; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0xb0; + reg2[1] = 0x01; + i2c_transfer(c->adapter, &msg, 1); -static int tda8290_tune(struct i2c_client *c) + reg2[0] = 0xc0; + reg2[1] = 0x19 + (t->tda827x_lpsel << 1); + i2c_transfer(c->adapter, &msg, 1); +} + +static void tda827xa_agcf(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - struct i2c_msg easy_mode = - { I2C_ADDR_TDA8290, 0, 2, t->i2c_easy_mode }; - struct i2c_msg set_freq = - { I2C_ADDR_TDA8275, 0, 8, t->i2c_set_freq }; - - i2c_transfer(c->adapter, &easy_mode, 1); - i2c_transfer(c->adapter, i2c_msg_prolog, ARRAY_SIZE(i2c_msg_prolog)); + unsigned char data[] = {0x80, 0x2c}; + struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data, + .flags = 0, .len = 2}; + i2c_transfer(c->adapter, &msg, 1); +} - i2c_transfer(c->adapter, &set_freq, 1); - i2c_transfer(c->adapter, i2c_msg_config, ARRAY_SIZE(i2c_msg_config)); +/*---------------------------------------------------------------------*/ - msleep(550); - i2c_transfer(c->adapter, i2c_msg_epilog, ARRAY_SIZE(i2c_msg_epilog)); - return 0; +static void tda8290_i2c_bridge(struct i2c_client *c, int close) +{ + unsigned char enable[2] = { 0x21, 0xC0 }; + unsigned char disable[2] = { 0x21, 0x80 }; + unsigned char *msg; + if(close) { + msg = enable; + i2c_master_send(c, msg, 2); + /* let the bridge stabilize */ + msleep(20); + } else { + msg = disable; + i2c_master_send(c, msg, 2); + } } -static void set_frequency(struct tuner *t, u16 ifc, unsigned int freq) +/*---------------------------------------------------------------------*/ + +static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) { - u32 N; + struct tuner *t = i2c_get_clientdata(c); + unsigned char soft_reset[] = { 0x00, 0x00 }; + unsigned char easy_mode[] = { 0x01, t->tda8290_easy_mode }; + unsigned char expert_mode[] = { 0x01, 0x80 }; + unsigned char gainset_off[] = { 0x28, 0x14 }; + unsigned char if_agc_spd[] = { 0x0f, 0x88 }; + unsigned char adc_head_6[] = { 0x05, 0x04 }; + unsigned char adc_head_9[] = { 0x05, 0x02 }; + unsigned char adc_head_12[] = { 0x05, 0x01 }; + unsigned char pll_bw_nom[] = { 0x0d, 0x47 }; + unsigned char pll_bw_low[] = { 0x0d, 0x27 }; + unsigned char gainset_2[] = { 0x28, 0x64 }; + unsigned char agc_rst_on[] = { 0x0e, 0x0b }; + unsigned char agc_rst_off[] = { 0x0e, 0x09 }; + unsigned char if_agc_set[] = { 0x0f, 0x81 }; + unsigned char addr_adc_sat = 0x1a; + unsigned char addr_agc_stat = 0x1d; + unsigned char addr_pll_stat = 0x1b; + unsigned char adc_sat, agc_stat, + pll_stat; + + i2c_master_send(c, easy_mode, 2); + i2c_master_send(c, soft_reset, 2); + msleep(1); + + i2c_master_send(c, expert_mode, 2); + i2c_master_send(c, gainset_off, 2); + i2c_master_send(c, if_agc_spd, 2); + if (t->tda8290_easy_mode & 0x60) + i2c_master_send(c, adc_head_9, 2); + else + i2c_master_send(c, adc_head_6, 2); + i2c_master_send(c, pll_bw_nom, 2); + + tda8290_i2c_bridge(c, 1); + if (t->tda827x_ver != 0) + tda827xa_tune(c, ifc, freq); + else + tda827x_tune(c, ifc, freq); + /* adjust headroom resp. gain */ + i2c_master_send(c, &addr_adc_sat, 1); + i2c_master_recv(c, &adc_sat, 1); + i2c_master_send(c, &addr_agc_stat, 1); + i2c_master_recv(c, &agc_stat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if (pll_stat & 0x80) + tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); + else + tuner_dbg("tda8290 not locked, no signal?\n"); + if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat <20))) { + tuner_dbg("adjust gain, step 1. Agc: %d\n", agc_stat); + i2c_master_send(c, gainset_2, 2); + msleep(100); + i2c_master_send(c, &addr_agc_stat, 1); + i2c_master_recv(c, &agc_stat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if ((agc_stat > 115) || !(pll_stat & 0x80)) { + tuner_dbg("adjust gain, step 2. Agc: %d\n", agc_stat); + if (t->tda827x_ver != 0) + tda827xa_agcf(c); + else + tda827x_agcf(c); + msleep(100); + i2c_master_send(c, &addr_agc_stat, 1); + i2c_master_recv(c, &agc_stat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if((agc_stat > 115) || !(pll_stat & 0x80)) { + tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); + i2c_master_send(c, adc_head_12, 2); + i2c_master_send(c, pll_bw_low, 2); + msleep(100); + } + } + } - if (t->mode == V4L2_TUNER_RADIO) - freq = freq / 1000; + /* l/ l' deadlock? */ + if(t->tda8290_easy_mode & 0x60) { + i2c_master_send(c, &addr_adc_sat, 1); + i2c_master_recv(c, &adc_sat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if ((adc_sat > 20) || !(pll_stat & 0x80)) { + i2c_master_send(c, agc_rst_on, 2); + msleep(40); + i2c_master_send(c, agc_rst_off, 2); + } + } - N = (((freq<<3)+ifc)&0x3fffc); - - N = N >> get_freq_entry(div_table, freq); - t->i2c_set_freq[0] = 0; - t->i2c_set_freq[1] = (unsigned char)(N>>8); - t->i2c_set_freq[2] = (unsigned char) N; - t->i2c_set_freq[3] = 0x40; - t->i2c_set_freq[4] = 0x52; - t->i2c_set_freq[5] = get_freq_entry(band_table, freq); - t->i2c_set_freq[6] = get_freq_entry(agc_table, freq); - t->i2c_set_freq[7] = 0x8f; + tda8290_i2c_bridge(c, 0); + i2c_master_send(c, if_agc_set, 2); + return 0; } + +/*---------------------------------------------------------------------*/ + #define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC) #define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B) #define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H) @@ -179,26 +404,27 @@ static void set_frequency(struct tuner *t, u16 ifc, unsigned int freq) static void set_audio(struct tuner *t) { - t->i2c_easy_mode[0] = 0x01; + t->tda827x_lpsel = 0; if (t->std & V4L2_STD_MN) { - t->sgIF = 736; - t->i2c_easy_mode[1] = 0x01; + t->sgIF = 92; + t->tda8290_easy_mode = 0x01; + t->tda827x_lpsel = 1; } else if (t->std & V4L2_STD_B) { - t->sgIF = 864; - t->i2c_easy_mode[1] = 0x02; + t->sgIF = 108; + t->tda8290_easy_mode = 0x02; } else if (t->std & V4L2_STD_GH) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x04; + t->sgIF = 124; + t->tda8290_easy_mode = 0x04; } else if (t->std & V4L2_STD_PAL_I) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x08; + t->sgIF = 124; + t->tda8290_easy_mode = 0x08; } else if (t->std & V4L2_STD_DK) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x10; + t->sgIF = 124; + t->tda8290_easy_mode = 0x10; } else if (t->std & V4L2_STD_SECAM_L) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x20; + t->sgIF = 124; + t->tda8290_easy_mode = 0x20; } } @@ -207,15 +433,13 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); set_audio(t); - set_frequency(t, t->sgIF, freq); - tda8290_tune(c); + tda8290_tune(c, t->sgIF, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) { - struct tuner *t = i2c_get_clientdata(c); - set_frequency(t, 704, freq); - tda8290_tune(c); + /* if frequency is 5.5 MHz */ + tda8290_tune(c, 88, freq); } static int has_signal(struct i2c_client *c) @@ -228,24 +452,118 @@ static int has_signal(struct i2c_client *c) return (afc & 0x80)? 65535:0; } +/*---------------------------------------------------------------------*/ + static void standby(struct i2c_client *c) { - i2c_transfer(c->adapter, i2c_msg_standby, ARRAY_SIZE(i2c_msg_standby)); + struct tuner *t = i2c_get_clientdata(c); + unsigned char cb1[] = { 0x30, 0xD0 }; + unsigned char tda8290_standby[] = { 0x00, 0x02 }; + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; + + tda8290_i2c_bridge(c, 1); + if (t->tda827x_ver != 0) + cb1[1] = 0x90; + i2c_transfer(c->adapter, &msg, 1); + tda8290_i2c_bridge(c, 0); + i2c_master_send(c, tda8290_standby, 2); } -int tda8290_init(struct i2c_client *c) + +static void tda8290_init_if(struct i2c_client *c) +{ + unsigned char set_VS[] = { 0x30, 0x6F }; + unsigned char set_GP01_CF[] = { 0x20, 0x0B }; + + i2c_master_send(c, set_VS, 2); + i2c_master_send(c, set_GP01_CF, 2); +} + +static void tda8290_init_tuner(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, + 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; + unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, + 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, + .buf=tda8275_init, .len = 14}; + if (t->tda827x_ver != 0) + msg.buf = tda8275a_init; + + tda8290_i2c_bridge(c, 1); + i2c_transfer(c->adapter, &msg, 1); + tda8290_i2c_bridge(c, 0); +} + +/*---------------------------------------------------------------------*/ - strlcpy(c->name, "tda8290+75", sizeof(c->name)); +int tda8290_init(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + u8 data; + int i, ret, tuners_found; + u32 tuner_addrs; + struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; + + tda8290_i2c_bridge(c, 1); + /* probe for tuner chip */ + tuners_found = 0; + tuner_addrs = 0; + for (i=0x60; i<= 0x63; i++) { + msg.addr = i; + ret = i2c_transfer(c->adapter, &msg, 1); + if (ret == 1) { + tuners_found++; + tuner_addrs = (tuner_addrs << 8) + i; + } + } + /* if there is more than one tuner, we expect the right one is + behind the bridge and we choose the highest address that doesn't + give a response now + */ + tda8290_i2c_bridge(c, 0); + if(tuners_found > 1) + for (i = 0; i < tuners_found; i++) { + msg.addr = tuner_addrs & 0xff; + ret = i2c_transfer(c->adapter, &msg, 1); + if(ret == 1) + tuner_addrs = tuner_addrs >> 8; + else + break; + } + if (tuner_addrs == 0) { + tuner_addrs = 0x61; + tuner_info ("could not clearly identify tuner address, defaulting to %x\n", + tuner_addrs); + } else { + tuner_addrs = tuner_addrs & 0xff; + tuner_info ("setting tuner address to %x\n", tuner_addrs); + } + t->tda827x_addr = tuner_addrs; + msg.addr = tuner_addrs; + + tda8290_i2c_bridge(c, 1); + ret = i2c_transfer(c->adapter, &msg, 1); + if( ret != 1) + tuner_warn ("TDA827x access failed!\n"); + if ((data & 0x3c) == 0) { + strlcpy(c->name, "tda8290+75", sizeof(c->name)); + t->tda827x_ver = 0; + } else { + strlcpy(c->name, "tda8290+75a", sizeof(c->name)); + t->tda827x_ver = 2; + } tuner_info("tuner: type set to %s\n", c->name); + t->tv_freq = set_tv_freq; t->radio_freq = set_radio_freq; t->has_signal = has_signal; t->standby = standby; + t->tda827x_lpsel = 0; - i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge)); - i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init)); + tda8290_init_tuner(c); + tda8290_init_if(c); return 0; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e677869afcf3..b9f1acf30caf 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -28,7 +28,7 @@ /* standard i2c insmod options */ static unsigned short normal_i2c[] = { - 0x4b, /* tda8290 */ + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, I2C_CLIENT_END diff --git a/include/media/tuner.h b/include/media/tuner.h index 94a9511479a1..8058be63ad0e 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -192,9 +192,11 @@ struct tuner { unsigned int radio_if2; /* used by tda8290 */ - unsigned char i2c_easy_mode[2]; - unsigned char i2c_set_freq[8]; - unsigned int sgIF; + unsigned char tda8290_easy_mode; + unsigned char tda827x_lpsel; + unsigned char tda827x_addr; + unsigned char tda827x_ver; + unsigned int sgIF; /* function ptrs */ void (*tv_freq)(struct i2c_client *c, unsigned int freq); -- cgit v1.2.3 From 79436633dbced18aa348f8669ef507109f851303 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:49 -0800 Subject: [PATCH] v4l: 809: some changes to allow compiling cx88 and saa7134 - Some changes to allow compiling cx88 and saa7134 without V4L1 support. - This patch will help obsoleting V4L1 API. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-video.c | 9 +++- drivers/media/video/saa7134/saa7134-video.c | 6 ++- drivers/media/video/saa7134/saa7134.h | 2 +- include/linux/videodev.h | 74 +--------------------------- include/linux/videodev2.h | 76 +++++++++++++++++++++++++++++ include/media/video-buf.h | 2 +- 6 files changed, 92 insertions(+), 77 deletions(-) (limited to 'include') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index f22ccb65de1c..cedd1d79ac13 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -34,6 +34,9 @@ #include "cx88.h" +/* Include V4L1 specific functions. Should be removed soon */ +#include + MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -1187,7 +1190,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return cx8800_try_fmt(dev,fh,f); } - +#ifdef HAVE_V4L1 /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1213,6 +1216,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } return 0; } +#endif case VIDIOC_REQBUFS: return videobuf_reqbufs(get_queue(fh), arg); @@ -1244,7 +1248,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, res_free(dev,fh,res); return 0; } - default: return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl ); } @@ -1537,6 +1540,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, *id = 0; return 0; } +#ifdef HAVE_V4L1 case VIDIOCSTUNER: { struct video_tuner *v = arg; @@ -1547,6 +1551,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, cx88_call_i2c_clients(core,VIDIOCSTUNER,v); return 0; } +#endif case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index caeb47c68b8b..632ebe8724ec 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -30,6 +30,9 @@ #include "saa7134-reg.h" #include "saa7134.h" +/* Include V4L1 specific functions. Should be removed soon */ +#include + /* ------------------------------------------------------------------ */ static unsigned int video_debug = 0; @@ -2060,7 +2063,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return saa7134_try_fmt(dev,fh,f); } - +#ifdef HAVE_V4L1 case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; @@ -2085,6 +2088,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } return 0; } +#endif case VIDIOC_REQBUFS: return videobuf_reqbufs(saa7134_queue(fh),arg); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 064c2f7a8c12..cd28a6a7b972 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 22e6e4bad7b8..23276cede540 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -1,57 +1,16 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H -#include #include -#define HAVE_V4L2 1 +#define HAVE_V4L1 1 + #include #ifdef __KERNEL__ -#include #include -#include - -struct video_device -{ - /* device info */ - struct device *dev; - char name[32]; - int type; /* v4l1 */ - int type2; /* v4l2 */ - int hardware; - int minor; - - /* device ops + callbacks */ - struct file_operations *fops; - void (*release)(struct video_device *vfd); - - - /* obsolete -- fops->owner is used instead */ - struct module *owner; - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; - - /* for videodev.c intenal usage -- please don't touch */ - int users; /* video_exclusive_{open|close} ... */ - struct semaphore lock; /* ... helper function uses these */ - char devfs_name[64]; /* devfs */ - struct class_device class_dev; /* sysfs */ -}; - -#define VIDEO_MAJOR 81 - -#define VFL_TYPE_GRABBER 0 -#define VFL_TYPE_VBI 1 -#define VFL_TYPE_RADIO 2 -#define VFL_TYPE_VTX 3 -extern int video_register_device(struct video_device *, int type, int nr); -extern void video_unregister_device(struct video_device *); extern struct video_device* video_devdata(struct file*); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) @@ -68,11 +27,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -/* helper functions to alloc / release struct video_device, the - later can be used for video_device->release() */ -struct video_device *video_device_alloc(void); -void video_device_release(struct video_device *vfd); - /* helper functions to access driver private data. */ static inline void *video_get_drvdata(struct video_device *dev) { @@ -86,27 +40,8 @@ static inline void video_set_drvdata(struct video_device *dev, void *data) extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); -extern int video_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); #endif /* __KERNEL__ */ -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - struct video_capability { char name[32]; @@ -260,9 +195,6 @@ struct video_key __u32 flags; }; - -#define VIDEO_MAX_FRAME 32 - struct video_mbuf { int size; /* Total memory to map */ @@ -270,10 +202,8 @@ struct video_mbuf int offsets[VIDEO_MAX_FRAME]; }; - #define VIDEO_NO_UNIT (-1) - struct video_unit { int video; /* Video minor */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 090091560c36..df0f9a24944a 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -18,6 +18,82 @@ #endif #include /* need __user */ +#include +#include + +#define HAVE_V4L2 1 + +/* + * Common stuff for both V4L1 and V4L2 + * Moved from videodev.h + */ + +#define VIDEO_MAX_FRAME 32 + +#define VFL_TYPE_GRABBER 0 +#define VFL_TYPE_VBI 1 +#define VFL_TYPE_RADIO 2 +#define VFL_TYPE_VTX 3 + +struct video_device +{ + /* device info */ + struct device *dev; + char name[32]; + int type; /* v4l1 */ + int type2; /* v4l2 */ + int hardware; + int minor; + + /* device ops + callbacks */ + struct file_operations *fops; + void (*release)(struct video_device *vfd); + + + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; + + /* for videodev.c intenal usage -- please don't touch */ + int users; /* video_exclusive_{open|close} ... */ + struct semaphore lock; /* ... helper function uses these */ + char devfs_name[64]; /* devfs */ + struct class_device class_dev; /* sysfs */ +}; + +#define VIDEO_MAJOR 81 + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + +extern int video_register_device(struct video_device *, int type, int nr); +extern void video_unregister_device(struct video_device *); +extern int video_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + +/* helper functions to alloc / release struct video_device, the + later can be used for video_device->release() */ +struct video_device *video_device_alloc(void); +void video_device_release(struct video_device *vfd); + /* * M I S C E L L A N E O U S */ diff --git a/include/media/video-buf.h b/include/media/video-buf.h index ee8eb15c0ea6..8ecfd78e0027 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -17,7 +17,7 @@ * (at your option) any later version. */ -#include +#include #define UNSET (-1U) -- cgit v1.2.3 From 1a9ca74d22065355d61bb6395590378040e7366d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:54 -0800 Subject: [PATCH] v4l: 815: commented obsoleted stuff at videodev headers - Commented obsoleted stuff at videodev headers. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 1 - include/linux/videodev.h | 10 ---------- include/linux/videodev2.h | 7 ------- 3 files changed, 18 deletions(-) (limited to 'include') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 16a6d2da7391..06644e230b47 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1671,7 +1671,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, return -ENOMEM; } - dev->vdev->owner = THIS_MODULE; dev->vdev->type = VID_TYPE_CAPTURE; if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 23276cede540..392592a040c5 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -27,16 +27,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -/* helper functions to access driver private data. */ -static inline void *video_get_drvdata(struct video_device *dev) -{ - return dev->priv; -} - -static inline void video_set_drvdata(struct video_device *dev, void *data) -{ - dev->priv = data; -} extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index df0f9a24944a..65829a510aca 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -50,13 +50,6 @@ struct video_device void (*release)(struct video_device *vfd); - /* obsolete -- fops->owner is used instead */ - struct module *owner; - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ -- cgit v1.2.3 From 01cb9633e1b294c604c2dfa01dcac95daf775213 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:38:00 -0800 Subject: [PATCH] v4l: 826: unify whitespaces - Unify whitespaces. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 2 +- include/media/tuner.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 2aeae864edc7..0dde6af251dd 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -535,7 +535,7 @@ int tda8290_init(struct i2c_client *c) if (tuner_addrs == 0) { tuner_addrs = 0x61; tuner_info ("could not clearly identify tuner address, defaulting to %x\n", - tuner_addrs); + tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info ("setting tuner address to %x\n", tuner_addrs); diff --git a/include/media/tuner.h b/include/media/tuner.h index 8058be63ad0e..5196d9eac442 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -214,6 +214,7 @@ extern int tda8290_init(struct i2c_client *c); extern int tea5767_tuner_init(struct i2c_client *c); extern int default_tuner_init(struct i2c_client *c); extern int tea5767_autodetection(struct i2c_client *c); +extern int tda8290_probe(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ -- cgit v1.2.3 From f958b68d40b870f5a0d1582f094bc93a53af7cd7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:01 -0800 Subject: [PATCH] v4l: 829: fixed user mode compiling - Fixed user mode compiling. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/videodev.h | 12 ++++++++++++ include/linux/videodev2.h | 18 ++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 392592a040c5..91140091ced2 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -27,6 +27,18 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } +#if OBSOLETE_OWNER /* to be removed in 2.6.15 */ +/* helper functions to access driver private data. */ +static inline void *video_get_drvdata(struct video_device *dev) +{ + return dev->priv; +} + +static inline void video_set_drvdata(struct video_device *dev, void *data) +{ + dev->priv = data; +} +#endif extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65829a510aca..cbe15edbe668 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -15,12 +15,13 @@ */ #ifdef __KERNEL__ #include /* need struct timeval */ +#include +#include #endif #include /* need __user */ -#include -#include +#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.15 */ #define HAVE_V4L2 1 /* @@ -30,6 +31,8 @@ #define VIDEO_MAX_FRAME 32 +#ifdef __KERNEL__ + #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 @@ -50,6 +53,15 @@ struct video_device void (*release)(struct video_device *vfd); +#if OBSOLETE_OWNER /* to be removed in 2.6.15 */ + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; +#endif /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ @@ -87,6 +99,8 @@ extern int video_usercopy(struct inode *inode, struct file *file, struct video_device *video_device_alloc(void); void video_device_release(struct video_device *vfd); +#endif + /* * M I S C E L L A N E O U S */ -- cgit v1.2.3 From c12097fd9adb07810fb28f70df5462c0603463cc Mon Sep 17 00:00:00 2001 From: Michael Schimek Date: Tue, 8 Nov 2005 21:38:24 -0800 Subject: [PATCH] v4l: 876: moved some user defines to be out of kernel define - Moved some user defines to be out of __KERNEL__ define. Signed-off-by: Michael Schimek Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/videodev2.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index cbe15edbe668..e8a0d22df54f 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -31,6 +31,21 @@ #define VIDEO_MAX_FRAME 32 +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + #ifdef __KERNEL__ #define VFL_TYPE_GRABBER 0 @@ -72,21 +87,6 @@ struct video_device #define VIDEO_MAJOR 81 -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - extern int video_register_device(struct video_device *, int type, int nr); extern void video_unregister_device(struct video_device *); extern int video_usercopy(struct inode *inode, struct file *file, -- cgit v1.2.3 From e0ec29b7e5aa1f4f1ff73ebd3003336dbe83e174 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 Nov 2005 21:38:26 -0800 Subject: [PATCH] v4l: 885: second round of i2c ids redefinition cleanup - Second round of i2c IDs redefinition cleanup. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bt832.c | 1 - drivers/media/video/msp3400.c | 1 - drivers/media/video/saa6588.c | 1 - drivers/media/video/saa7134/saa6752hs.c | 1 - drivers/media/video/saa7134/saa7134.h | 1 - drivers/media/video/tda7432.c | 1 - drivers/media/video/tda9875.c | 1 - drivers/media/video/tda9887.c | 1 - drivers/media/video/tvaudio.c | 3 +-- drivers/media/video/tveeprom.c | 4 ---- include/linux/i2c-id.h | 11 +++++++---- 11 files changed, 8 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 3e42493a4e0a..e4063950ae57 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -32,7 +32,6 @@ #include #include -#include #include "bttv.h" #include "bt832.h" diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index ba2c95842fba..d603229c9f2f 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -54,7 +54,6 @@ #include #include -#include #include "msp3400.h" #define OPMODE_AUTO -1 diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 5252a4ca3fd1..23ea548a71e0 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -31,7 +31,6 @@ #include #include -#include #include "rds.h" diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 2bf5cf79eec1..cdd1ed9c8065 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -13,7 +13,6 @@ #include #include -#include #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 #define MPEG_VIDEO_MAX_BITRATE_MAX 27000 diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 1365f1f32fee..4273ded9d174 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 14cf1d357c3b..d32737dd2142 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -50,7 +50,6 @@ #include "bttv.h" #include -#include #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 5a9faefc3640..a5e37dc91f39 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -32,7 +32,6 @@ #include "bttv.h" #include -#include static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 9d6b6f57abcd..4249127c0a1d 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -11,7 +11,6 @@ #include #include -#include /* Chips: TDA9885 (PAL, NTSC) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 75901b030730..c31bf28b73fe 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -31,7 +31,6 @@ #include #include -#include #include "tvaudio.h" @@ -1438,7 +1437,7 @@ static struct CHIPDESC chiplist[] = { }, { .name = "pic16c54 (PV951)", - .id = I2C_DRIVERID_PIC16C54_PV951, + .id = I2C_DRIVERID_PIC16C54_PV9, .insmodopt = &pic16c54, .addr_lo = I2C_PIC16C54 >> 1, .addr_hi = I2C_PIC16C54>> 1, diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index d83a33618119..72e8741e8b59 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -658,10 +658,6 @@ EXPORT_SYMBOL(tveeprom_read); /* run, just call the exported tveeprom_* directly, there is no point in */ /* using the indirect way via i2c_driver->command() */ -#ifndef I2C_DRIVERID_TVEEPROM -# define I2C_DRIVERID_TVEEPROM I2C_DRIVERID_EXP2 -#endif - static unsigned short normal_i2c[] = { 0xa0 >> 1, I2C_CLIENT_END, diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 1ce4b54caa21..815675f1e349 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -27,10 +27,10 @@ * ---- Driver types ----------------------------------------------------- * device id name + number function description, i2c address(es) * - * Range 1000-1999 range is defined in sensors/sensors.h - * Range 0x100 - 0x1ff is for V4L2 Common Components + * Range 1000-1999 range is defined in sensors/sensors.h + * Range 0x100 - 0x1ff is for V4L2 Common Components * Range 0xf000 - 0xffff is reserved for local experimentation, and should - * never be used in official drivers + * never be used in official drivers */ #define I2C_DRIVERID_MSP3400 1 @@ -99,6 +99,9 @@ #define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_SAA7114H 64 /* video decoder */ #define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */ +#define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ +#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ +#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ @@ -111,7 +114,7 @@ #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ #define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */ -/* IDs -- Use DRIVERIDs 1000-1999 for sensors. +/* IDs -- Use DRIVERIDs 1000-1999 for sensors. These were originally in sensors.h in the lm_sensors package */ #define I2C_DRIVERID_LM78 1002 #define I2C_DRIVERID_LM75 1003 -- cgit v1.2.3 From c3b3924ea0843d6956e5f87c3a4be09f460fe923 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:29 -0800 Subject: [PATCH] v4l: 887: i2c id h updated to reflect the newer drivers - I2c-id.h Updated to reflect the newer drivers. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/i2c-id.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 815675f1e349..74abaecdb572 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -102,7 +102,11 @@ #define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ #define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ #define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ - +#define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */ +#define I2C_DRIVERID_CS53L32A 70 /* cs53l32a audio processor */ +#define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ +#define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ +#define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ #define I2C_DRIVERID_EXP1 0xF1 @@ -193,6 +197,7 @@ #define I2C_HW_B_NVIDIA 0x01001c /* nvidia framebuffer driver */ #define I2C_HW_B_SAVAGE 0x01001d /* savage framebuffer driver */ #define I2C_HW_B_RADEON 0x01001e /* radeon framebuffer driver */ +#define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ /* --- PCF 8584 based algorithms */ #define I2C_HW_P_LP 0x020000 /* Parallel port interface */ -- cgit v1.2.3 From ad07d93ae7884a72a293eb4efb61a872f109ebd5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:36 -0800 Subject: [PATCH] v4l: 897: saa7146 fix - Fixing headers to compile cleanly. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 1 - include/media/saa7146_vv.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index f6acce820791..5b09f52dd669 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "em28xx.h" #include diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index f3aa24f8131c..64691753721e 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -1,7 +1,7 @@ #ifndef __SAA7146_VV__ #define __SAA7146_VV__ -#include +#include #include #include -- cgit v1.2.3 From 22ae2550f65bc322e6bdeff9d3948bbb5e0a9b67 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:38 -0800 Subject: [PATCH] v4l: 899: remove media id.h - Removed media id.h file Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/media/id.h | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 include/media/id.h (limited to 'include') diff --git a/include/media/id.h b/include/media/id.h deleted file mode 100644 index 4f58d73e7029..000000000000 --- a/include/media/id.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - */ - -/* FIXME: this temporarely, until these are included in linux/i2c-id.h */ - -/* drivers */ -#ifndef I2C_DRIVERID_TVMIXER -# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0 -#endif -#ifndef I2C_DRIVERID_TVAUDIO -# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1 -#endif - -/* chips */ -#ifndef I2C_DRIVERID_DPL3518 -# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2 -#endif -#ifndef I2C_DRIVERID_TDA9873 -# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3 -#endif -#ifndef I2C_DRIVERID_TDA9875 -# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4 -#endif -#ifndef I2C_DRIVERID_PIC16C54_PV951 -# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5 -#endif -#ifndef I2C_DRIVERID_TDA7432 -# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6 -#endif -#ifndef I2C_DRIVERID_TDA9874 -# define I2C_DRIVERID_TDA9874 I2C_DRIVERID_EXP0+7 -#endif -#ifndef I2C_DRIVERID_SAA6752HS -# define I2C_DRIVERID_SAA6752HS I2C_DRIVERID_EXP0+8 -#endif -#ifndef I2C_DRIVERID_WM8775 -#define I2C_DRIVERID_WM8775 I2C_DRIVERID_EXP0+9 -#endif -#ifndef I2C_DRIVERID_CS53L32A -#define I2C_DRIVERID_CS53L32A I2C_DRIVERID_EXP0+10 -#endif -#ifndef I2C_DRIVERID_CX25840 -#define I2C_DRIVERID_CX25840 I2C_DRIVERID_EXP0+11 -#endif -#ifndef I2C_DRIVERID_SAA7115 -#define I2C_DRIVERID_SAA7115 I2C_DRIVERID_EXP0+12 -#endif -#ifndef I2C_DRIVERID_SAA7127 -#define I2C_DRIVERID_SAA7127 I2C_DRIVERID_EXP0+13 -#endif -- cgit v1.2.3 From 90e9df7f186876584b938e01fcf7f40a50c950b9 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:38:42 -0800 Subject: [PATCH] V4L: 904: added dvb support for tda8275a philips tiger reference design Added dvb support for tda8275a (Philips Tiger reference design) Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 37 ++++++ drivers/media/video/saa7134/saa7134-dvb.c | 192 ++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + include/media/tuner.h | 2 +- 4 files changed, 231 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 9e1c51c08f21..d9b3fb0f3eff 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2490,6 +2490,29 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, + [SAA7134_BOARD_PHILIPS_TIGER] = { + .name = "Philips Tiger reference design", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2919,6 +2942,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1043, .subdevice = 0x4862, .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = PCI_VENDOR_ID_PHILIPS, + .subdevice = 0x2018, + .driver_data = SAA7134_BOARD_PHILIPS_TIGER, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3177,6 +3206,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); } break; + case SAA7134_BOARD_PHILIPS_TIGER: + /* this is a hybrid board, initialize to analog mode */ + { + u8 data[] = { 0x3c, 0x33, 0x68}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + i2c_transfer(&dev->i2c_adap, &msg, 1); + } + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index aaac12e8adbf..d1d1abc55718 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -626,8 +626,196 @@ static struct tda1004x_config tda827x_lifeview_config = { .pll_sleep = philips_tda827x_pll_sleep, .request_firmware = NULL, }; + +/* ------------------------------------------------------------------ */ + +struct tda827xa_data { + u32 lomax; + u8 svco; + u8 spd; + u8 scr; + u8 sbs; + u8 gc3; +}; + +static struct tda827xa_data tda827xa_dvbt[] = { + { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, + { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}}; + + +static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct saa7134_dev *dev = fe->dvb->priv; + u8 tuner_buf[14]; + unsigned char reg2[2]; + + struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = tuner_buf}; + int i, tuner_freq, if_freq; + u32 N; + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + if_freq = 4000000; + break; + case BANDWIDTH_7_MHZ: + if_freq = 4500000; + break; + default: /* 8 MHz or Auto */ + if_freq = 5000000; + break; + } + tuner_freq = params->frequency + if_freq; + + i = 0; + while (tda827xa_dvbt[i].lomax < tuner_freq) { + if(tda827xa_dvbt[i + 1].lomax == 0) + break; + i++; + } + + N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; + tuner_buf[0] = 0; // subaddress + tuner_buf[1] = N >> 8; + tuner_buf[2] = N & 0xff; + tuner_buf[3] = 0; + tuner_buf[4] = 0x16; + tuner_buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + + tda827xa_dvbt[i].sbs; + tuner_buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); + tuner_buf[7] = 0x0c; + tuner_buf[8] = 0x06; + tuner_buf[9] = 0x24; + tuner_buf[10] = 0xff; + tuner_buf[11] = 0x60; + tuner_buf[12] = 0x00; + tuner_buf[13] = 0x39; // lpsel + msg.len = 14; + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + return -EIO; + + msg.buf= reg2; + msg.len = 2; + reg2[0] = 0x60; + reg2[1] = 0x3c; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + reg2[0] = 0xa0; + reg2[1] = 0x40; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + msleep(2); + /* correct CP value */ + reg2[0] = 0x30; + reg2[1] = 0x10 + tda827xa_dvbt[i].scr; + msg.len = 2; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + msleep(550); + reg2[0] = 0x50; + reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); + i2c_transfer(&dev->i2c_adap, &msg, 1); + + return 0; + +} + +static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 tda827xa_sleep[] = { 0x30, 0x90}; + struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, + .len = sizeof(tda827xa_sleep) }; + i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); + +} + +/* ------------------------------------------------------------------ */ + +static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + int ret; + struct saa7134_dev *dev = fe->dvb->priv; + static u8 tda8290_close[] = { 0x21, 0xc0}; + static u8 tda8290_open[] = { 0x21, 0x80}; + struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; + /* close tda8290 i2c bridge */ + tda8290_msg.buf = tda8290_close; + ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); + if (ret != 1) + return -EIO; + msleep(20); + ret = philips_tda827xa_pll_set(0x61, fe, params); + if (ret != 0) + return ret; + /* open tda8290 i2c bridge */ + tda8290_msg.buf = tda8290_open; + i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); + return ret; +}; + +static int philips_tiger_dvb_mode(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 data[] = { 0x3c, 0x33, 0x6a}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static void philips_tiger_analog_mode(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 data[] = { 0x3c, 0x33, 0x68}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + + i2c_transfer(&dev->i2c_adap, &msg, 1); + philips_tda827xa_pll_sleep( 0x61, fe); +} + +static struct tda1004x_config philips_tiger_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .if_freq = TDA10046_FREQ_045, + .pll_init = philips_tiger_dvb_mode, + .pll_set = philips_tiger_pll_set, + .pll_sleep = philips_tiger_analog_mode, + .request_firmware = NULL, +}; + #endif +/* ------------------------------------------------------------------ */ + #ifdef HAVE_NXT200X static struct nxt200x_config avertvhda180 = { .demod_address = 0x0a, @@ -688,6 +876,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, &dev->i2c_adap); break; + case SAA7134_BOARD_PHILIPS_TIGER: + dev->dvb.frontend = tda10046_attach(&philips_tiger_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4273ded9d174..a82468a07676 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -207,6 +207,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78 #define SAA7134_BOARD_PCTV_CARDBUS 79 #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 +#define SAA7134_BOARD_PHILIPS_TIGER 81 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/include/media/tuner.h b/include/media/tuner.h index 5196d9eac442..9184e534b7ef 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -211,10 +211,10 @@ extern unsigned const int tuner_count; extern int microtune_init(struct i2c_client *c); extern int tda8290_init(struct i2c_client *c); +extern int tda8290_probe(struct i2c_client *c); extern int tea5767_tuner_init(struct i2c_client *c); extern int default_tuner_init(struct i2c_client *c); extern int tea5767_autodetection(struct i2c_client *c); -extern int tda8290_probe(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ -- cgit v1.2.3 From eac94356c8f9f7d3854ed0290a406b13bfe8df4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:43 -0800 Subject: [PATCH] V4L: 907: em28xx cleanups and fixes - Em28xx cleanups and fixes. - Some cleanups and audio amux adjust. - em28xx will allways try, by default, the biggest size alt. - Fixes audio mux code. - Fixes some logs. - Adds support for digital output for WinTV USB2 board. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 15 ++-- drivers/media/video/em28xx/em28xx-core.c | 17 +--- drivers/media/video/em28xx/em28xx-video.c | 107 +++++++++++----------- drivers/media/video/msp3400.c | 142 +++++++++++++++++++++++++++--- include/linux/videodev2.h | 1 + 5 files changed, 201 insertions(+), 81 deletions(-) (limited to 'include') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 49107fd0c0d3..57779e63f35d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -128,7 +128,7 @@ struct em28xx_board em28xx_boards[] = { .input = {{ .type = EM28XX_VMUX_TELEVISION, .vmux = 0, - .amux = 0, + .amux = 6, },{ .type = EM28XX_VMUX_SVIDEO, .vmux = 2, @@ -261,9 +261,11 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { struct tveeprom tv; + struct v4l2_audioout ao; #ifdef CONFIG_MODULES request_module("tveeprom"); request_module("ir-kbd-i2c"); + request_module("msp3400"); #endif /* Call first TVeeprom */ @@ -273,10 +275,13 @@ void em28xx_card_setup(struct em28xx *dev) dev->tuner_type= tv.tuner_type; if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { dev->has_msp34xx=1; - } else dev->has_msp34xx=0; - em28xx_write_regs_req(dev,0x06,0x00,"\x40",1);// Serial Bus Frequency Select Register - em28xx_write_regs_req(dev,0x0f,0x00,"\x87",1);// XCLK Frequency Select Register - em28xx_write_regs_req(dev,0x88,0x0d,"\xd0",1); + memset (&ao,0,sizeof(ao)); + + ao.index=2; + ao.mode=V4L2_AUDMODE_32BITS; + em28xx_i2c_call_clients(dev, VIDIOC_S_AUDOUT, &ao); + } else + dev->has_msp34xx=0; } } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 045547e17656..5cc850666fd7 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -797,20 +797,9 @@ int em28xx_set_alternate(struct em28xx *dev) dev->alt = alt; if (dev->alt == 0) { int i; - if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ - for(i=0;i< EM28XX_MAX_ALT; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) - dev->alt=i; - }else{ - unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ - em28xx_coredbg("minimum isoc packet size: %u", min_pkt_size); - dev->alt = 7; - for (i = 1; i < EM28XX_MAX_ALT; i += 2) /* FIXME: skip even alternate: why do they not work? */ - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; - break; - } - } + for(i=0;i< EM28XX_MAX_ALT; i++) + if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) + dev->alt=i; } if (dev->alt != prev_alt) { diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 54f21242ccbf..0bbfce03172d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -277,6 +277,35 @@ static void em28xx_empty_framequeues(struct em28xx *dev) } } +static void video_mux(struct em28xx *dev, int index) +{ + int input, ainput; + + input = INPUT(index)->vmux; + dev->ctl_input = index; + dev->ctl_ainput = INPUT(index)->amux; + + em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); + + + em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); + + if (dev->has_msp34xx) { + em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput); + ainput = EM28XX_AUDIO_SRC_TUNER; + em28xx_audio_source(dev, ainput); + } else { + switch (dev->ctl_ainput) { + case 0: + ainput = EM28XX_AUDIO_SRC_TUNER; + break; + default: + ainput = EM28XX_AUDIO_SRC_LINE; + } + em28xx_audio_source(dev, ainput); + } +} + /* * em28xx_v4l2_open() * inits the device and starts isoc transfer @@ -298,7 +327,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) filp->private_data=dev; - em28xx_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d\n", dev->users); if (!down_read_trylock(&em28xx_disconnect)) return -ERESTARTSYS; @@ -352,6 +381,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->state |= DEV_INITIALIZED; + video_mux(dev, 0); + err: up(&dev->lock); up_read(&em28xx_disconnect); @@ -386,7 +417,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) int errCode; struct em28xx *dev=filp->private_data; - em28xx_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d\n", dev->users); down(&dev->lock); @@ -404,7 +435,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* set alternate 0 */ dev->alt = 0; - em28xx_videodbg("setting alternate 0"); + em28xx_videodbg("setting alternate 0\n"); errCode = usb_set_interface(dev->udev, 0, 0); if (errCode < 0) { em28xx_errdev ("cannot change alternate number to 0 (error=%i)\n", @@ -434,20 +465,20 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present"); + em28xx_videodbg("device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device misconfigured; close and open it again"); + em28xx_videodbg("device misconfigured; close and open it again\n"); up(&dev->fileop_lock); return -EIO; } if (dev->io == IO_MMAP) { em28xx_videodbg ("IO method is set to mmap; close and open" - " the device again to choose the read method"); + " the device again to choose the read method\n"); up(&dev->fileop_lock); return -EINVAL; } @@ -524,9 +555,9 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) return POLLERR; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present"); + em28xx_videodbg("device not present\n"); } else if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device is misconfigured; close and open it again"); + em28xx_videodbg("device is misconfigured; close and open it again\n"); } else { if (dev->io == IO_NONE) { if (!em28xx_request_buffers @@ -595,14 +626,14 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("mmap: device not present"); + em28xx_videodbg("mmap: device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg ("mmap: Device is misconfigured; close and " - "open it again"); + "open it again\n"); up(&dev->fileop_lock); return -EIO; } @@ -618,7 +649,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) break; } if (i == dev->num_frames) { - em28xx_videodbg("mmap: user supplied mapping address is out of range"); + em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); up(&dev->fileop_lock); return -EINVAL; } @@ -632,7 +663,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, vma->vm_page_prot)) { - em28xx_videodbg("mmap: rename page map failed"); + em28xx_videodbg("mmap: rename page map failed\n"); up(&dev->fileop_lock); return -EAGAIN; } @@ -749,7 +780,7 @@ static int em28xx_stream_interrupt(struct em28xx *dev) else if (ret) { dev->state |= DEV_MISCONFIGURED; em28xx_videodbg("device is misconfigured; close and " - "open /dev/video%d again", dev->vdev->minor); + "open /dev/video%d again\n", dev->vdev->minor); return ret; } @@ -800,28 +831,6 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) return 0; } -static void video_mux(struct em28xx *dev, int index) -{ - int input, ainput; - - input = INPUT(index)->vmux; - dev->ctl_input = index; - - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); - - dev->ctl_ainput = INPUT(index)->amux; - - switch (dev->ctl_ainput) { - case 0: - ainput = EM28XX_AUDIO_SRC_TUNER; - break; - default: - ainput = EM28XX_AUDIO_SRC_LINE; - } - - em28xx_audio_source(dev, ainput); -} - /* * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from @@ -1062,7 +1071,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x", t->signal, + em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, t->afc); return 0; } @@ -1146,7 +1155,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ - em28xx_videodbg("VIDIOC_STREAMON: starting stream"); + em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); return 0; } @@ -1160,7 +1169,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, return -EINVAL; if (dev->stream == STREAM_ON) { - em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream"); + em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1234,7 +1243,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, { struct v4l2_format *format = arg; - em28xx_videodbg("VIDIOC_G_FMT: type=%s", + em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == @@ -1253,7 +1262,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - em28xx_videodbg("VIDIOC_G_FMT: %dx%d", dev->width, + em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, dev->height); return 0; } @@ -1274,7 +1283,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, /* int both_fields; */ - em28xx_videodbg("%s: type=%s", + em28xx_videodbg("%s: type=%s\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", @@ -1288,7 +1297,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - em28xx_videodbg("%s: requested %dx%d", + em28xx_videodbg("%s: requested %dx%d\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1347,7 +1356,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - em28xx_videodbg("%s: returned %dx%d (%d, %d)", + em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1359,13 +1368,13 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { em28xx_videodbg("VIDIOC_S_FMT failed. " - "Unmap the buffers first."); + "Unmap the buffers first.\n"); return -EINVAL; } /* stop io in case it is already in progress */ if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_SET_FMT: interupting stream"); + em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1405,18 +1414,18 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, if (dev->io == IO_READ) { em28xx_videodbg ("method is set to read;" " close and open the device again to" - " choose the mmap I/O method"); + " choose the mmap I/O method\n"); return -EINVAL; } for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { - em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped"); + em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n"); return -EINVAL; } if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream"); + em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1430,7 +1439,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, dev->frame_current = NULL; - em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i", + em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", rb->count); dev->io = rb->count ? IO_MMAP : IO_NONE; return 0; diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index d603229c9f2f..b599f0554fb7 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -90,6 +90,8 @@ struct msp3400c { int stereo; int nicam_on; int acb; + int in_scart; + int i2s_mode; int main, second; /* sound carrier */ int input; int source; /* see msp34xxg_set_source */ @@ -364,12 +366,40 @@ static struct CARRIER_DETECT carrier_detect_65[] = { #define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT)) -/* ----------------------------------------------------------------------- */ +/* ----------------------------------------------------------------------- * + * bits 9 8 5 - SCART DSP input Select: + * 0 0 0 - SCART 1 to DSP input (reset position) + * 0 1 0 - MONO to DSP input + * 1 0 0 - SCART 2 to DSP input + * 1 1 1 - Mute DSP input + * + * bits 11 10 6 - SCART 1 Output Select: + * 0 0 0 - undefined (reset position) + * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS) + * 1 0 0 - MONO input to SCART 1 Output + * 1 1 0 - SCART 1 DA to SCART 1 Output + * 0 0 1 - SCART 2 DA to SCART 1 Output + * 0 1 1 - SCART 1 Input to SCART 1 Output + * 1 1 1 - Mute SCART 1 Output + * + * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART): + * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position) + * 0 1 0 - SCART 1 Input to SCART 2 Output + * 1 0 0 - MONO input to SCART 2 Output + * 0 0 1 - SCART 2 DA to SCART 2 Output + * 0 1 1 - SCART 2 Input to SCART 2 Output + * 1 1 0 - Mute SCART 2 Output + * + * Bits 4 to 0 should be zero. + * ----------------------------------------------------------------------- */ static int scarts[3][9] = { /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + /* SCART DSP Input select */ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + /* SCART1 Output select */ { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + /* SCART2 Output select */ { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, }; @@ -381,13 +411,23 @@ static void msp3400c_set_scart(struct i2c_client *client, int in, int out) { struct msp3400c *msp = i2c_get_clientdata(client); - if (-1 == scarts[out][in]) - return; + msp->in_scart=in; + + if (in<=2) { + if (-1 == scarts[out][in]) + return; + + msp->acb &= ~scarts[out][SCART_MASK]; + msp->acb |= scarts[out][in]; + } else + msp->acb = 0xf60; /* Mute Input and SCART 1 Output */ + + dprintk("msp34xx: scart switch: %s => %d (ACB=0x%04x)\n", + scart_names[in], out, msp->acb); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb); - dprintk("msp34xx: scart switch: %s => %d\n", scart_names[in], out); - msp->acb &= ~scarts[out][SCART_MASK]; - msp->acb |= scarts[out][in]; - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb); + /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } /* ------------------------------------------------------------------------ */ @@ -1235,7 +1275,8 @@ static int msp3410d_thread(void *data) msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); + msp3400c_write(client, I2C_MSP3400C_DFP, 0x13, msp->acb); + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); msp3400c_restore_dfp(client); /* monitor tv audio mode */ @@ -1275,6 +1316,8 @@ static int msp34xxg_reset(struct i2c_client *client) 0x0f20 /* mute DSP input, mute SCART 1 */)) return -1; + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); + /* step-by-step initialisation, as described in the manual */ modus = msp34xx_modus(msp->norm); std = msp34xx_standard(msp->norm); @@ -1371,6 +1414,8 @@ static int msp34xxg_thread(void *data) 0x13, /* ACB */ msp->acb)) return -1; + + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } dprintk("msp34xxg: thread: exit\n"); return 0; @@ -1539,6 +1584,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) msp->treble = 32768; msp->input = -1; msp->muted = 0; + msp->i2s_mode = 0; for (i = 0; i < DFP_COUNT; i++) msp->dfp_regs[i] = -1; @@ -1735,6 +1781,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) } } + static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); @@ -1745,6 +1792,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case AUDC_SET_INPUT: dprintk("msp34xx: AUDC_SET_INPUT(%d)\n",*sarg); + if (*sarg == msp->input) break; msp->input = *sarg; @@ -1923,6 +1971,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } + /* msp34xx specific */ + case MSP_SET_MATRIX: + { + struct msp_matrix *mspm = arg; + + dprintk("msp34xx: MSP_SET_MATRIX\n"); + msp3400c_set_scart(client, mspm->input, mspm->output); + break; + } + /* --- v4l2 ioctls --- */ case VIDIOC_S_STD: { @@ -1941,6 +1999,33 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if (i->index != 0) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_TUNER; + switch (i->index) { + case AUDIO_RADIO: + strcpy(i->name,"Radio"); + break; + case AUDIO_EXTERN_1: + strcpy(i->name,"Extern 1"); + break; + case AUDIO_EXTERN_2: + strcpy(i->name,"Extern 2"); + break; + case AUDIO_TUNER: + strcpy(i->name,"Television"); + break; + default: + return -EINVAL; + } + return 0; + } + case VIDIOC_G_AUDIO: { struct v4l2_audio *a = arg; @@ -2032,13 +2117,44 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } - /* msp34xx specific */ - case MSP_SET_MATRIX: + case VIDIOC_G_AUDOUT: { - struct msp_matrix *mspm = arg; + struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + + memset(a,0,sizeof(*a)); + + switch (a->index) { + case 0: + strcpy(a->name,"Scart1 Out"); + break; + case 1: + strcpy(a->name,"Scart2 Out"); + break; + case 2: + strcpy(a->name,"I2S Out"); + break; + default: + return -EINVAL; + } + break; + + } + case VIDIOC_S_AUDOUT: + { + struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + + if (a->index<0||a->index>2) + return -EINVAL; + + if (a->index==2) { + if (a->mode == V4L2_AUDMODE_32BITS) + msp->i2s_mode=1; + else + msp->i2s_mode=0; + } +printk("Setting audio out on msp34xx to input %i, mode %i\n",a->index,msp->i2s_mode); + msp3400c_set_scart(client,msp->in_scart,a->index); - dprintk("msp34xx: MSP_SET_MATRIX\n"); - msp3400c_set_scart(client, mspm->input, mspm->output); break; } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index e8a0d22df54f..67c61b4bf2e7 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -885,6 +885,7 @@ struct v4l2_audio /* Flags for the 'mode' field */ #define V4L2_AUDMODE_AVL 0x00001 +#define V4L2_AUDMODE_32BITS 0x00002 struct v4l2_audioout { -- cgit v1.2.3 From f1bcef8874ab33b1e517b79a9b9df7309a996877 Mon Sep 17 00:00:00 2001 From: Tyler Trafford Date: Tue, 8 Nov 2005 21:38:46 -0800 Subject: [PATCH] V4L: 911: added support for ntsc 4.43 video standard Added support for NTSC 4.43 video standard. Signed-off-by: Tyler Trafford Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- include/linux/videodev2.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 4cd3db492456..e016480c3468 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -749,7 +749,7 @@ static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827xa_sleep[] = { 0x30, 0x90}; struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, - .len = sizeof(tda827xa_sleep) }; + .len = sizeof(tda827xa_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 67c61b4bf2e7..a114fff6568b 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -627,6 +627,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) @@ -664,7 +665,8 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ V4L2_STD_PAL_60 |\ - V4L2_STD_NTSC) + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) #define V4L2_STD_625_50 (V4L2_STD_PAL |\ V4L2_STD_PAL_N |\ V4L2_STD_PAL_Nc |\ -- cgit v1.2.3 From e4fc27618b75234b721c4a13d0e0d9d07e75e641 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:09 -0800 Subject: [PATCH] fbcon: Console Rotation - Prepare fbcon for console rotation This patch series implements generic code to rotate the console at 90, 180, and 270 degrees. The implementation is completely done in the framebuffer console level, thus no changes to the framebuffer layer or to the drivers are needed. Console rotation is required by some Sharp-based devices where the natural orientation of the display is not at 0 degrees. Also, users that have displays that can pivot will benefit by having a console in portrait mode if they so desire. The choice to implement the code in the console layer rather than in the framebuffer layer is due to the following reasons: - it's fast - it does not require driver changes - it can coexist with devices that can rotate the display at the hardware level - it complements graphics applications that can do display rotation The changes to core fbcon are minimal-- recognition of the console rotation angle so it can swap directions, origins and axes (xres vs yres, xpanstep vs ypanstep, xoffset vs yoffset, etc) and storage of the rotation angle per display. The bulk of the code that does the actual drawing to the screen are placed in separate files. Each angle of rotation has separate methods (bmove, clear, putcs, cursor, update_start which is derived from update_var, and clear_margins). To mimimize processing time, the fontdata are pre-rotated at each console switch (only if the font or the angle has changed). The option can be compiled out (CONFIG_FRAMEBUFFER_CONSOLE_ROTATION = n) if rotation is not needed. Choosing the rotation angle can be done in several ways: 1. boot option fbcon=rotate:n, where n = 0 - normal n = 1 - 90 degrees (clockwise) n = 2 - 180 degrees (upside down) n = 3 - 270 degrees (counterclockwise) 2. echo n > /sys/class/graphics/fb[num]/con_rotate where n is the same as described above. It sets the angle of rotation of the current console 3 echo n > /sys/class/graphics/fb[num]/con_rotate_all where n is the same as described above. Globally sets the angle of rotation. GOTCHAS: The option, especially at angles of 90 and 270 degrees, will exercise the least used code of drivers. Namely, at these angles, panning is done in the x-axis, so it can reveal bugs in the driver if xpanstep is set incorrectly. A workaround is to set xpanstep = 0. Secondly, at these angles, the framebuffer memory access can be unaligned if (fontheight * bpp) % 32 ~= 0 which can reveal bugs in the drivers imageblit, fillrect and copyarea functions. (I think cfbfillrect may have this buglet). A workaround is to use a standard 8x16 font. Speed: The scrolling speed difference between 0 and 180 degrees is minimal, somewhere areound 1-2%. At 90 or 270 degress, speed drops down to a vicinity of 30-40%. This is understandable because the blit direction is across the framebuffer "direction." Scrolling will be helped at these angles if xpanstep is not equal to zero, use of 8x16 fonts, and setting xres_virtual >= xres * 2. Note: The code is tested on little-endian only, so I don't know if it will work in big-endian. Please let me know, it will take only less than a minute of your time. This patch prepares fbcon for console rotation and contains the following changes: - add rotate field in struct fbcon_ops to keep fbcon's current rotation angle - add con_rotate field in struct display to store per-display rotation angle - create a private copy of the current var to fbcon. This will prevent fbcon from directly manipulating info->var, especially the fields xoffset, yoffset and vmode. - add ability to swap pertinent axes (xres, yres; xpanstep, ypanstep; etc) depending on the rotation angle - change global update_var() (function that sets the screen start address) as an fbcon method update_start. This is required because the axes, start offset, and/or direction can be reversed depending on the rotation angle. - add fbcon method rotate_font() which will rotate each character bitmap to the correct angle of rotation. - add fbcon boot option 'rotate' to select the angle of rotation at bootime. Currently does nothing until all patches are applied. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 10 ++ drivers/video/console/bitblit.c | 46 +++---- drivers/video/console/fbcon.c | 285 +++++++++++++++++++++++++-------------- drivers/video/console/fbcon.h | 58 +++++++- drivers/video/console/tileblit.c | 13 ++ include/linux/fb.h | 12 +- 6 files changed, 286 insertions(+), 138 deletions(-) (limited to 'include') diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index fadf7c5d216e..94c5f1392cce 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -101,6 +101,16 @@ config FRAMEBUFFER_CONSOLE help Low-level framebuffer-based console driver. +config FRAMEBUFFER_CONSOLE_ROTATION + bool "Framebuffer Console Rotation" + depends on FRAMEBUFFER_CONSOLE + help + Enable display rotation for the framebuffer console. This is done + in software and may be significantly slower than a normally oriented + display. Note that the rotation is done at the console level only + such that other users of the framebuffer will remain normally + oriented. + config STI_CONSOLE tristate "STI text console" depends on PARISC diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 67857b3cfc8b..e65fc3ef7630 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -22,35 +22,6 @@ /* * Accelerated handlers. */ -#define FBCON_ATTRIBUTE_UNDERLINE 1 -#define FBCON_ATTRIBUTE_REVERSE 2 -#define FBCON_ATTRIBUTE_BOLD 4 - -static inline int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - -static inline int get_attribute(struct fb_info *info, u16 c) -{ - int attribute = 0; - - if (fb_get_color_depth(&info->var, &info->fix) == 1) { - if (attr_underline(c)) - attribute |= FBCON_ATTRIBUTE_UNDERLINE; - if (attr_reverse(c)) - attribute |= FBCON_ATTRIBUTE_REVERSE; - if (attr_bold(c)) - attribute |= FBCON_ATTRIBUTE_BOLD; - } - - return attribute; -} - static inline void update_attr(u8 *dst, u8 *src, int attribute, struct vc_data *vc) { @@ -418,6 +389,18 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ops->cursor_reset = 0; } +static int bit_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_bitops(struct fbcon_ops *ops) { ops->bmove = bit_bmove; @@ -425,6 +408,11 @@ void fbcon_set_bitops(struct fbcon_ops *ops) ops->putcs = bit_putcs; ops->clear_margins = bit_clear_margins; ops->cursor = bit_cursor; + ops->update_start = bit_update_start; + ops->rotate_font = NULL; + + if (ops->rotate) + fbcon_set_rotate(ops); } EXPORT_SYMBOL(fbcon_set_bitops); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3cf1b61ff1f8..b5d678c73252 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -107,6 +107,8 @@ enum { }; struct display fb_display[MAX_NR_CONSOLES]; +EXPORT_SYMBOL(fb_display); + static signed char con2fb_map[MAX_NR_CONSOLES]; static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static int logo_height; @@ -130,6 +132,9 @@ static char fontname[40]; /* current fb_info */ static int info_idx = -1; +/* console rotation */ +static int rotate; + static const struct consw fb_con; #define CM_SOFTBACK (8) @@ -176,7 +181,6 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines); /* * Internal routines */ -static __inline__ int real_y(struct display *p, int ypos); static __inline__ void ywrap_up(struct vc_data *vc, int count); static __inline__ void ywrap_down(struct vc_data *vc, int count); static __inline__ void ypan_up(struct vc_data *vc, int count); @@ -203,6 +207,13 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) } #endif +static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + + ops->rotate = FB_ROTATE_UR; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -422,6 +433,14 @@ static int __init fb_console_setup(char *this_opt) last_fb_vc = simple_strtoul(options, &options, 10) - 1; fbcon_is_default = 0; } + + if (!strncmp(options, "rotate:", 7)) { + options += 7; + if (*options) + rotate = simple_strtoul(options, &options, 0); + if (rotate > 3) + rotate = 0; + } } return 0; } @@ -558,16 +577,24 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, if ((info->flags & FBINFO_MISC_TILEBLITTING)) fbcon_set_tileops(vc, info, p, ops); - else + else { + struct display *disp; + + disp = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, disp); fbcon_set_bitops(ops); + } } #else static void set_blitting_type(struct vc_data *vc, struct fb_info *info, struct display *p) { struct fbcon_ops *ops = info->fbcon_par; + struct display *disp; info->flags &= ~FBINFO_MISC_TILEBLITTING; + disp = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, disp); fbcon_set_bitops(ops); } #endif /* CONFIG_MISC_TILEBLITTING */ @@ -627,6 +654,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, fbcon_del_cursor_timer(oldinfo); kfree(ops->cursor_state.mask); kfree(ops->cursor_data); + kfree(ops->fontbuffer); kfree(oldinfo->fbcon_par); oldinfo->fbcon_par = NULL; module_put(oldinfo->fbops->owner); @@ -827,7 +855,9 @@ static const char *fbcon_startup(void) memset(ops, 0, sizeof(struct fbcon_ops)); ops->currcon = -1; ops->graphics = 1; + ops->cur_rotate = -1; info->fbcon_par = ops; + p->con_rotate = rotate; set_blitting_type(vc, info, NULL); if (info->fix.type != FB_TYPE_TEXT) { @@ -866,8 +896,10 @@ static const char *fbcon_startup(void) vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ } - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); DPRINTK("mode: %s\n", info->fix.id); @@ -953,8 +985,6 @@ static void fbcon_init(struct vc_data *vc, int init) (info->fix.type == FB_TYPE_TEXT)) logo = 0; - info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ - if (var_to_display(p, &info->var, info)) return; @@ -986,13 +1016,18 @@ static void fbcon_init(struct vc_data *vc, int init) if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); + ops = info->fbcon_par; + p->con_rotate = rotate; + set_blitting_type(vc, info, NULL); + cols = vc->vc_cols; rows = vc->vc_rows; - new_cols = info->var.xres / vc->vc_font.width; - new_rows = info->var.yres / vc->vc_font.height; + new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + new_cols /= vc->vc_font.width; + new_rows /= vc->vc_font.height; vc_resize(vc, new_cols, new_rows); - ops = info->fbcon_par; /* * We must always set the mode. The mode of the previous console * driver could be in the same resolution but we are using different @@ -1030,6 +1065,12 @@ static void fbcon_init(struct vc_data *vc, int init) if (vc == svc && softback_buf) fbcon_update_softback(vc); + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } + } static void fbcon_deinit(struct vc_data *vc) @@ -1066,15 +1107,6 @@ static void fbcon_deinit(struct vc_data *vc) * restriction is simplicity & efficiency at the moment. */ -static __inline__ int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, int width) { @@ -1162,13 +1194,6 @@ static int scrollback_phys_max = 0; static int scrollback_max = 0; static int scrollback_current = 0; -static int update_var(int con, struct fb_info *info) -{ - if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon) - return fb_pan_display(info, &info->var); - return 0; -} - /* * If no vc is existent yet, just set struct display */ @@ -1178,7 +1203,6 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va struct display *p = &fb_display[unit]; struct display *t = &fb_display[fg_console]; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; @@ -1194,9 +1218,9 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, struct display *p = &fb_display[vc->vc_num], *t; struct vc_data **default_mode = vc->vc_display_fg; struct vc_data *svc = *default_mode; + struct fbcon_ops *ops = info->fbcon_par; int rows, cols, charcnt = 256; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; t = &fb_display[svc->vc_num]; @@ -1213,9 +1237,10 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, var->activate = FB_ACTIVATE_NOW; info->var.activate = var->activate; - info->var.yoffset = info->var.xoffset = 0; + var->yoffset = info->var.yoffset; + var->xoffset = info->var.xoffset; fb_set_var(info, var); - + ops->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -1231,9 +1256,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); - cols = var->xres / vc->vc_font.width; - rows = var->yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); + if (CON_IS_VISIBLE(vc)) { update_screen(vc); if (softback_buf) @@ -1244,15 +1272,16 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, static __inline__ void ywrap_up(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1262,15 +1291,16 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) static __inline__ void ywrap_down(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1289,10 +1319,11 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1303,6 +1334,7 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1312,12 +1344,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; if (redraw) fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1337,10 +1370,11 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1351,6 +1385,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1359,12 +1394,14 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) p->yscroll += p->vrows - vc->vc_rows; redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; + if (redraw) fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1838,31 +1875,41 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s height, width); } -static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, +static __inline__ void updatescrollmode(struct display *p, + struct fb_info *info, struct vc_data *vc) { + struct fbcon_ops *ops = info->fbcon_par; int fh = vc->vc_font.height; int cap = info->flags; - int good_pan = (cap & FBINFO_HWACCEL_YPAN) - && divides(info->fix.ypanstep, vc->vc_font.height) - && info->var.yres_virtual > info->var.yres; - int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) - && divides(info->fix.ywrapstep, vc->vc_font.height) - && divides(vc->vc_font.height, info->var.yres_virtual); + u16 t = 0; + int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, + info->fix.xpanstep); + int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); + int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, + info->var.xres_virtual); + int good_pan = (cap & FBINFO_HWACCEL_YPAN) && + divides(ypan, vc->vc_font.height) && vyres > yres; + int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && + divides(ywrap, vc->vc_font.height) && + divides(vc->vc_font.height, vyres); int reading_fast = cap & FBINFO_READS_FAST; - int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED); - int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && !(cap & FBINFO_HWACCEL_DISABLED); - - p->vrows = info->var.yres_virtual/fh; - if (info->var.yres > (fh * (vc->vc_rows + 1))) - p->vrows -= (info->var.yres - (fh * vc->vc_rows)) / fh; - if ((info->var.yres % fh) && (info->var.yres_virtual % fh < - info->var.yres % fh)) + int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && + !(cap & FBINFO_HWACCEL_DISABLED); + int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && + !(cap & FBINFO_HWACCEL_DISABLED); + + p->vrows = vyres/fh; + if (yres > (fh * (vc->vc_rows + 1))) + p->vrows -= (yres - (fh * vc->vc_rows)) / fh; + if ((yres % fh) && (vyres % fh < yres % fh)) p->vrows--; if (good_wrap || good_pan) { if (reading_fast || fast_copyarea) - p->scrollmode = good_wrap ? SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; + p->scrollmode = good_wrap ? + SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; else p->scrollmode = good_wrap ? SCROLL_REDRAW : SCROLL_PAN_REDRAW; @@ -1878,17 +1925,23 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, unsigned int height) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var = info->var; - int x_diff, y_diff; - int fw = vc->vc_font.width; - int fh = vc->vc_font.height; - - var.xres = width * fw; - var.yres = height * fh; + int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; + + virt_w = FBCON_SWAP(ops->rotate, width, height); + virt_h = FBCON_SWAP(ops->rotate, height, width); + virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width, + vc->vc_font.height); + virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height, + vc->vc_font.width); + var.xres = virt_w * virt_fw; + var.yres = virt_h * virt_fh; x_diff = info->var.xres - var.xres; y_diff = info->var.yres - var.yres; - if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) { + if (x_diff < 0 || x_diff > virt_fw || + y_diff < 0 || y_diff > virt_fh) { struct fb_videomode *mode; DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); @@ -1898,7 +1951,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, display_to_var(&var, p); fb_videomode_to_var(&var, mode); - if (width > var.xres/fw || height > var.yres/fh) + if (virt_w > var.xres/virt_fw || virt_h > var.yres/virt_fh) return -EINVAL; DPRINTK("resize now %ix%i\n", var.xres, var.yres); @@ -1908,6 +1961,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, fb_set_var(info, &var); } var_to_display(p, &info->var, info); + ops->var = info->var; } updatescrollmode(p, info, vc); return 0; @@ -1916,11 +1970,13 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, static int fbcon_switch(struct vc_data *vc) { struct fb_info *info, *old_info = NULL; + struct fbcon_ops *ops; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; int i, prev_console; info = registered_fb[con2fb_map[vc->vc_num]]; + ops = info->fbcon_par; if (softback_top) { if (softback_lines) @@ -1939,7 +1995,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = FBCON_LOGO_CANSHOW; } - prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon; + prev_console = ops->currcon; if (prev_console != -1) old_info = registered_fb[con2fb_map[prev_console]]; /* @@ -1952,9 +2008,9 @@ static int fbcon_switch(struct vc_data *vc) */ for (i = 0; i < FB_MAX; i++) { if (registered_fb[i] != NULL && registered_fb[i]->fbcon_par) { - struct fbcon_ops *ops = registered_fb[i]->fbcon_par; + struct fbcon_ops *o = registered_fb[i]->fbcon_par; - ops->currcon = vc->vc_num; + o->currcon = vc->vc_num; } } memset(&var, 0, sizeof(struct fb_var_screeninfo)); @@ -1966,8 +2022,11 @@ static int fbcon_switch(struct vc_data *vc) * in fb_set_var() */ info->var.activate = var.activate; - info->var.yoffset = info->var.xoffset = p->yscroll = 0; + var.yoffset = info->var.yoffset; + var.xoffset = info->var.xoffset; + var.vmode = info->var.vmode; fb_set_var(info, &var); + ops->var = info->var; if (old_info != NULL && old_info != info) { if (info->fbops->fb_set_par) @@ -1977,7 +2036,12 @@ static int fbcon_switch(struct vc_data *vc) } set_blitting_type(vc, info, p); - ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; + ops->cursor_reset = 1; + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; @@ -1997,10 +2061,11 @@ static int fbcon_switch(struct vc_data *vc) scrollback_phys_max = 0; break; } + scrollback_max = 0; scrollback_current = 0; - - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); fbcon_clear_margins(vc, 0); @@ -2047,6 +2112,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; fb_set_var(info, &var); ops->graphics = 0; + ops->var = info->var; } } @@ -2135,6 +2201,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, const u8 * data, int userfont) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int resize; int cnt; @@ -2214,9 +2281,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, } if (resize) { - /* reset wrap/pan */ - info->var.xoffset = info->var.yoffset = p->yscroll = 0; - vc_resize(vc, info->var.xres / w, info->var.yres / h); + int cols, rows; + + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= w; + rows /= h; + vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc) && softback_buf) fbcon_update_softback(vc); } else if (CON_IS_VISIBLE(vc) @@ -2444,6 +2515,7 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) static int fbcon_scrolldelta(struct vc_data *vc, int lines) { struct fb_info *info = registered_fb[con2fb_map[fg_console]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[fg_console]; int offset, limit, scrollback_old; @@ -2520,9 +2592,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) offset += limit; else if (offset >= limit) offset -= limit; - info->var.xoffset = 0; - info->var.yoffset = offset * vc->vc_font.height; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = offset * vc->vc_font.height; + ops->update_start(info); + if (!scrollback_current) fbcon_cursor(vc, CM_DRAW); return 0; @@ -2570,22 +2644,25 @@ static void fbcon_modechanged(struct fb_info *info) if (!ops || ops->currcon < 0) return; vc = vc_cons[ops->currcon].d; - if (vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info) + if (vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[ops->currcon]] != info) return; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); if (CON_IS_VISIBLE(vc)) { var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); if (softback_buf) @@ -2610,18 +2687,20 @@ static void fbcon_set_all_vcs(struct fb_info *info) continue; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc)) { updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); if (softback_buf) diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index b68e0e2c2d16..846a5a4e736c 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -27,15 +27,15 @@ */ struct display { - /* Filled in by the frame buffer device */ - u_short inverse; /* != 0 text black on white as default */ /* Filled in by the low-level console driver */ const u_char *fontdata; int userfont; /* != 0 if fontdata kmalloc()ed */ u_short scrollmode; /* Scroll Method */ + u_short inverse; /* != 0 text black on white as default */ short yscroll; /* Hardware scrolling */ int vrows; /* number of virtual rows */ int cursor_shape; + int con_rotate; u32 xres_virtual; u32 yres_virtual; u32 height; @@ -52,6 +52,8 @@ struct display { struct fb_videomode *mode; }; +extern struct display fb_display[]; + struct fbcon_ops { void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width); @@ -63,8 +65,12 @@ struct fbcon_ops { void (*clear_margins)(struct vc_data *vc, struct fb_info *info, int bottom_only); void (*cursor)(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, int fg, int bg); - + struct display *p, int mode, int softback_lines, + int fg, int bg); + int (*update_start)(struct fb_info *info); + int (*rotate_font)(struct fb_info *info, struct vc_data *vc, + struct display *p); + struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ struct timer_list cursor_timer; /* Cursor timer */ struct fb_cursor cursor_state; int currcon; /* Current VC. */ @@ -73,7 +79,12 @@ struct fbcon_ops { int blank_state; int graphics; int flags; + int rotate; + int cur_rotate; char *cursor_data; + u8 *fontbuffer; + u8 *fontdata; + u32 fd_size; }; /* * Attribute Decoding @@ -168,4 +179,43 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); + +#define FBCON_ATTRIBUTE_UNDERLINE 1 +#define FBCON_ATTRIBUTE_REVERSE 2 +#define FBCON_ATTRIBUTE_BOLD 4 + +static inline int real_y(struct display *p, int ypos) +{ + int rows = p->vrows; + + ypos += p->yscroll; + return ypos < rows ? ypos : ypos - rows; +} + + +static inline int get_attribute(struct fb_info *info, u16 c) +{ + int attribute = 0; + + if (fb_get_color_depth(&info->var, &info->fix) == 1) { + if (attr_underline(c)) + attribute |= FBCON_ATTRIBUTE_UNDERLINE; + if (attr_reverse(c)) + attribute |= FBCON_ATTRIBUTE_REVERSE; + if (attr_bold(c)) + attribute |= FBCON_ATTRIBUTE_BOLD; + } + + return attribute; +} + +#define FBCON_SWAP(i,r,v) ({ \ + typeof(r) _r = (r); \ + typeof(v) _v = (v); \ + (void) (&_r == &_v); \ + (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) + +#define fbcon_set_rotate(x) do {} while(0) + #endif /* _VIDEO_FBCON_H */ + diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index 7f76e2c6a4a1..cb25324a5635 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c @@ -118,6 +118,18 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, info->tileops->fb_tilecursor(info, &cursor); } +static int tile_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops) { @@ -128,6 +140,7 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, ops->putcs = tile_putcs; ops->clear_margins = tile_clear_margins; ops->cursor = tile_cursor; + ops->update_start = tile_update_start; if (p) { map.width = vc->vc_font.width; diff --git a/include/linux/fb.h b/include/linux/fb.h index e7ff98e395f6..51791dc5d4dc 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -201,6 +201,14 @@ struct fb_bitfield { #define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ #define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ +/* + * Display rotation support + */ +#define FB_ROTATE_UR 0 +#define FB_ROTATE_CW 1 +#define FB_ROTATE_UD 2 +#define FB_ROTATE_CCW 3 + #define PICOS2KHZ(a) (1000000000UL/(a)) #define KHZ2PICOS(a) (1000000000UL/(a)) @@ -489,9 +497,9 @@ struct fb_cursor_user { #define FB_EVENT_MODE_DELETE 0x04 /* A driver registered itself */ #define FB_EVENT_FB_REGISTERED 0x05 -/* get console to framebuffer mapping */ +/* CONSOLE-SPECIFIC: get console to framebuffer mapping */ #define FB_EVENT_GET_CONSOLE_MAP 0x06 -/* set console to framebuffer mapping */ +/* CONSOLE-SPECIFIC: set console to framebuffer mapping */ #define FB_EVENT_SET_CONSOLE_MAP 0x07 /* A display blank is requested */ #define FB_EVENT_BLANK 0x08 -- cgit v1.2.3 From 9c44e5f6c211a9b7313ded897f3135ef7d9ad3e2 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:10 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support to rotate the logo Add support for rotating and positioning of the logo. Rotation and position depends on 'int rotate' parameter added to fb_prepare_logo() and fb_show_logo(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 5 +- drivers/video/fbmem.c | 130 +++++++++++++++++++++++++++++++++++++----- include/linux/fb.h | 4 +- 3 files changed, 122 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b5d678c73252..26935e231a1d 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cols, int rows, int new_cols, int new_rows) { /* Need to make room for the logo */ + struct fbcon_ops *ops = info->fbcon_par; int cnt, erase = vc->vc_video_erase_char, step; unsigned short *save = NULL, *r, *q; @@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, */ if (fb_get_color_depth(&info->var, &info->fix) == 1) erase &= ~0x400; - logo_height = fb_prepare_logo(info); + logo_height = fb_prepare_logo(info, ops->rotate); logo_lines = (logo_height + vc->vc_font.height - 1) / vc->vc_font.height; q = (unsigned short *) (vc->vc_origin + @@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = fg_console; /* This is protected above by initmem_freed */ - fb_show_logo(info); + fb_show_logo(info, ops->rotate); update_region(vc, vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_size_row * (vc->vc_bottom - diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e2667ddab3f1..7a2a8fa50b3b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -323,9 +323,103 @@ static struct logo_data { const struct linux_logo *logo; } fb_logo; -int fb_prepare_logo(struct fb_info *info) +static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) +{ + u32 size = width * height, i; + + out += size - 1; + + for (i = size; i--; ) + *out-- = *in++; +} + +static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * j + w - i] = *in++; +} + +static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * (w - j) + i] = *in++; +} + +static void fb_rotate_logo(struct fb_info *info, u8 *dst, + struct fb_image *image, int rotate) +{ + u32 tmp; + + if (rotate == FB_ROTATE_UD) { + image->dx = info->var.xres - image->width; + image->dy = info->var.yres - image->height; + fb_rotate_logo_ud(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dx = info->var.xres - image->height; + fb_rotate_logo_cw(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CCW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dy = info->var.yres - image->width; + fb_rotate_logo_ccw(image->data, dst, image->width, + image->height); + } + + image->data = dst; +} + +static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, + int rotate) +{ + int x; + + if (rotate == FB_ROTATE_UR) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_UD) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx -= fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CCW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy -= fb_logo.logo->width + 8; + } + } +} + +int fb_prepare_logo(struct fb_info *info, int rotate) { int depth = fb_get_color_depth(&info->var, &info->fix); + int yres; memset(&fb_logo, 0, sizeof(struct logo_data)); @@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info) /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); - if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { + if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) + yres = info->var.yres; + else + yres = info->var.xres; + + if (fb_logo.logo && fb_logo.logo->height > yres) { fb_logo.logo = NULL; return 0; } + /* What depth we asked for might be different from what we get */ if (fb_logo.logo->type == LINUX_LOGO_CLUT224) fb_logo.depth = 8; @@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info) return fb_logo.logo->height; } -int fb_show_logo(struct fb_info *info) +int fb_show_logo(struct fb_info *info, int rotate) { u32 *palette = NULL, *saved_pseudo_palette = NULL; - unsigned char *logo_new = NULL; + unsigned char *logo_new = NULL, *logo_rotate = NULL; struct fb_image image; - int x; /* Return if the frame buffer is not mapped or suspended */ if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) @@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info) fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); } + image.dx = 0; + image.dy = 0; image.width = fb_logo.logo->width; image.height = fb_logo.logo->height; - image.dy = 0; - for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && - x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { - image.dx = x; - info->fbops->fb_imageblit(info, &image); + if (rotate) { + logo_rotate = kmalloc(fb_logo.logo->width * + fb_logo.logo->height, GFP_KERNEL); + if (logo_rotate) + fb_rotate_logo(info, logo_rotate, &image, rotate); } - + + fb_do_show_logo(info, &image, rotate); + kfree(palette); if (saved_pseudo_palette != NULL) info->pseudo_palette = saved_pseudo_palette; kfree(logo_new); + kfree(logo_rotate); return fb_logo.logo->height; } #else -int fb_prepare_logo(struct fb_info *info) { return 0; } -int fb_show_logo(struct fb_info *info) { return 0; } +int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } +int fb_show_logo(struct fb_info *info, int rotate) { return 0; } #endif /* CONFIG_LOGO */ static int fbmem_read_proc(char *buf, char **start, off_t offset, diff --git a/include/linux/fb.h b/include/linux/fb.h index 51791dc5d4dc..357dd3a0a01e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); -extern int fb_prepare_logo(struct fb_info *fb_info); -extern int fb_show_logo(struct fb_info *fb_info); +extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); +extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, u32 shift_high, u32 shift_low, u32 mod); -- cgit v1.2.3 From a812c94b94e3db76d1af68208fb3edef69070401 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:15 -0800 Subject: [PATCH] fbcon: Console Rotation - Add ability to control rotation via sysfs Add ability to set rotation via sysfs. The attributes are located in /sys/class/graphics/fb[n] and accepts 0 - unrotated; 1 - clockwise; 2 - upside down; 3 - counterclockwise. The attributes are: con_rotate (r/w) - set rotation of the active console con_rotate_all (w) - set rotation of all consoles rotate (r/w) - set rotation of the framebuffer, if supported. Currently, none of the drivers support this. This is probably temporary, since con_rotate and con_rotate_all are console-specific and has no business being under the fb device. However, until the console layer acquires it's own sysfs class, these attributes will temporarily reside here. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 72 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/fbmem.c | 22 +++++++++++++ drivers/video/fbsysfs.c | 67 ++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 7 +++++ 4 files changed, 168 insertions(+) (limited to 'include') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e829ba18e0a5..e7802ffe549a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -193,6 +193,8 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va int unit); static void fbcon_redraw_move(struct vc_data *vc, struct display *p, int line, int count, int dy); +static void fbcon_modechanged(struct fb_info *info); +static void fbcon_set_all_vcs(struct fb_info *info); #ifdef CONFIG_MAC /* @@ -218,6 +220,51 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) else ops->rotate = 0; } + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops= info->fbcon_par; + struct fb_info *fb_info; + + if (!ops || ops->currcon == -1) + return; + + fb_info = registered_fb[con2fb_map[ops->currcon]]; + + if (info == fb_info) { + struct display *p = &fb_display[ops->currcon]; + + if (rotate < 4) + p->con_rotate = rotate; + else + p->con_rotate = 0; + + fbcon_modechanged(info); + } +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct vc_data *vc; + struct display *p; + int i; + + if (!ops || ops->currcon < 0 || rotate > 3) + return; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + vc = vc_cons[i].d; + if (!vc || vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[i]] != info) + continue; + + p = &fb_display[vc->vc_num]; + p->con_rotate = rotate; + } + + fbcon_set_all_vcs(info); +} #else static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) { @@ -225,8 +272,25 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) ops->rotate = FB_ROTATE_UR; } + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + return; +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + return; +} #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ +static int fbcon_get_rotate(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + + return (ops) ? ops->rotate : 0; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -2864,6 +2928,14 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; + case FB_EVENT_SET_CON_ROTATE: + fbcon_rotate(info, *(int *)event->data); + break; + case FB_EVENT_GET_CON_ROTATE: + ret = fbcon_get_rotate(info); + break; + case FB_EVENT_SET_CON_ROTATE_ALL: + fbcon_rotate_all(info, *(int *)event->data); } return ret; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7a2a8fa50b3b..81b6cd23ea1d 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1319,6 +1319,28 @@ int fb_new_modelist(struct fb_info *info) return err; } +/** + * fb_con_duit - user<->fbcon passthrough + * @info: struct fb_info + * @event: notification event to be passed to fbcon + * @data: private data + * + * DESCRIPTION + * This function is an fbcon-user event passing channel + * which bypasses fbdev. This is hopefully temporary + * until a user interface for fbcon is created + */ +int fb_con_duit(struct fb_info *info, int event, void *data) +{ + struct fb_event evnt; + + evnt.info = info; + evnt.data = data; + + return notifier_call_chain(&fb_notifier_list, event, &evnt); +} +EXPORT_SYMBOL(fb_con_duit); + static char *video_options[FB_MAX]; static int ofonly; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 007c8e9b2b39..08dac9580d15 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -213,6 +213,70 @@ static ssize_t show_bpp(struct class_device *class_device, char *buf) return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } +static ssize_t store_rotate(struct class_device *class_device, const char *buf, + size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_var_screeninfo var; + char **last = NULL; + int err; + + var = fb_info->var; + var.rotate = simple_strtoul(buf, last, 0); + + if ((err = activate(fb_info, &var))) + return err; + + return count; +} + + +static ssize_t show_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); +} + +static ssize_t store_con_rotate(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE, &rotate); + release_console_sem(); + return count; +} + +static ssize_t store_con_rotate_all(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE_ALL, &rotate); + release_console_sem(); + return count; +} + +static ssize_t show_con_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + + acquire_console_sem(); + rotate = fb_con_duit(fb_info, FB_EVENT_GET_CON_ROTATE, NULL); + release_console_sem(); + return snprintf(buf, PAGE_SIZE, "%d\n", rotate); +} + static ssize_t store_virtual(struct class_device *class_device, const char * buf, size_t count) { @@ -440,6 +504,9 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), __ATTR(name, S_IRUGO, show_name, NULL), __ATTR(stride, S_IRUGO, show_stride, NULL), + __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), + __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), + __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/include/linux/fb.h b/include/linux/fb.h index 357dd3a0a01e..04a58f33ec53 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -508,6 +508,12 @@ struct fb_cursor_user { /* The resolution of the passed in fb_info about to change and all vc's should be changed */ #define FB_EVENT_MODE_CHANGE_ALL 0x0A +/* CONSOLE-SPECIFIC: set console rotation */ +#define FB_EVENT_SET_CON_ROTATE 0x0B +/* CONSOLE-SPECIFIC: get console rotation */ +#define FB_EVENT_GET_CON_ROTATE 0x0C +/* CONSOLE-SPECIFIC: rotate all consoles */ +#define FB_EVENT_SET_CON_ROTATE_ALL 0x0D struct fb_event { struct fb_info *info; @@ -836,6 +842,7 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix); extern int fb_get_options(char *name, char **option); extern int fb_new_modelist(struct fb_info *info); +extern int fb_con_duit(struct fb_info *info, int event, void *data); extern struct fb_info *registered_fb[FB_MAX]; extern int num_registered_fb; -- cgit v1.2.3 From c7f82d9c49e763f40f7ea7126a2c9f067bfde71f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 8 Nov 2005 21:39:19 -0800 Subject: [PATCH] fbdev: move ioctl32 code to fbmem.c The frame buffer layer already had some code dealing with compat ioctls, this patch moves over the remaining code from fs/compat_ioctl.c Signed-off-by: Arnd Bergmann Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 147 +++++++++++++++++++++++++++++++++++++++++-- fs/compat_ioctl.c | 143 ----------------------------------------- include/linux/compat_ioctl.h | 7 --- 3 files changed, 142 insertions(+), 155 deletions(-) (limited to 'include') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 81b6cd23ea1d..9f180096c896 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -933,18 +934,154 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } #ifdef CONFIG_COMPAT +struct fb_fix_screeninfo32 { + char id[16]; + compat_caddr_t smem_start; + u32 smem_len; + u32 type; + u32 type_aux; + u32 visual; + u16 xpanstep; + u16 ypanstep; + u16 ywrapstep; + u32 line_length; + compat_caddr_t mmio_start; + u32 mmio_len; + u32 accel; + u16 reserved[3]; +}; + +struct fb_cmap32 { + u32 start; + u32 len; + compat_caddr_t red; + compat_caddr_t green; + compat_caddr_t blue; + compat_caddr_t transp; +}; + +static int fb_getput_cmap(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct fb_cmap_user __user *cmap; + struct fb_cmap32 __user *cmap32; + __u32 data; + int err; + + cmap = compat_alloc_user_space(sizeof(*cmap)); + cmap32 = compat_ptr(arg); + + if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32))) + return -EFAULT; + + if (get_user(data, &cmap32->red) || + put_user(compat_ptr(data), &cmap->red) || + get_user(data, &cmap32->green) || + put_user(compat_ptr(data), &cmap->green) || + get_user(data, &cmap32->blue) || + put_user(compat_ptr(data), &cmap->blue) || + get_user(data, &cmap32->transp) || + put_user(compat_ptr(data), &cmap->transp)) + return -EFAULT; + + err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); + + if (!err) { + if (copy_in_user(&cmap32->start, + &cmap->start, + 2 * sizeof(__u32))) + err = -EFAULT; + } + return err; +} + +static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, + struct fb_fix_screeninfo32 __user *fix32) +{ + __u32 data; + int err; + + err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); + + data = (__u32) (unsigned long) fix->smem_start; + err |= put_user(data, &fix32->smem_start); + + err |= put_user(fix->smem_len, &fix32->smem_len); + err |= put_user(fix->type, &fix32->type); + err |= put_user(fix->type_aux, &fix32->type_aux); + err |= put_user(fix->visual, &fix32->visual); + err |= put_user(fix->xpanstep, &fix32->xpanstep); + err |= put_user(fix->ypanstep, &fix32->ypanstep); + err |= put_user(fix->ywrapstep, &fix32->ywrapstep); + err |= put_user(fix->line_length, &fix32->line_length); + + data = (__u32) (unsigned long) fix->mmio_start; + err |= put_user(data, &fix32->mmio_start); + + err |= put_user(fix->mmio_len, &fix32->mmio_len); + err |= put_user(fix->accel, &fix32->accel); + err |= copy_to_user(fix32->reserved, fix->reserved, + sizeof(fix->reserved)); + + return err; +} + +static int fb_get_fscreeninfo(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs; + struct fb_fix_screeninfo fix; + struct fb_fix_screeninfo32 __user *fix32; + int err; + + fix32 = compat_ptr(arg); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); + set_fs(old_fs); + + if (!err) + err = do_fscreeninfo_to_user(&fix, fix32); + + return err; +} + static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int fbidx = iminor(file->f_dentry->d_inode); + struct inode *inode = file->f_dentry->d_inode; + int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; - long ret; + long ret = -ENOIOCTLCMD; - if (fb->fb_compat_ioctl == NULL) - return -ENOIOCTLCMD; lock_kernel(); - ret = fb->fb_compat_ioctl(file, cmd, arg, info); + switch(cmd) { + case FBIOGET_VSCREENINFO: + case FBIOPUT_VSCREENINFO: + case FBIOPAN_DISPLAY: + case FBIOGET_CON2FBMAP: + case FBIOPUT_CON2FBMAP: + arg = (unsigned long) compat_ptr(arg); + case FBIOBLANK: + ret = fb_ioctl(inode, file, cmd, arg); + break; + + case FBIOGET_FSCREENINFO: + ret = fb_get_fscreeninfo(inode, file, cmd, arg); + break; + + case FBIOGETCMAP: + case FBIOPUTCMAP: + ret = fb_getput_cmap(inode, file, cmd, arg); + break; + + default: + if (fb->fb_compat_ioctl) + ret = fb->fb_compat_ioctl(file, cmd, arg, info); + break; + } unlock_kernel(); return ret; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 71c9d45c0624..26300fccb4fc 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -840,146 +840,6 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) return err ? -EFAULT : 0; } -struct fb_fix_screeninfo32 { - char id[16]; - compat_caddr_t smem_start; - u32 smem_len; - u32 type; - u32 type_aux; - u32 visual; - u16 xpanstep; - u16 ypanstep; - u16 ywrapstep; - u32 line_length; - compat_caddr_t mmio_start; - u32 mmio_len; - u32 accel; - u16 reserved[3]; -}; - -struct fb_cmap32 { - u32 start; - u32 len; - compat_caddr_t red; - compat_caddr_t green; - compat_caddr_t blue; - compat_caddr_t transp; -}; - -static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct fb_cmap_user __user *cmap; - struct fb_cmap32 __user *cmap32; - __u32 data; - int err; - - cmap = compat_alloc_user_space(sizeof(*cmap)); - cmap32 = compat_ptr(arg); - - if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32))) - return -EFAULT; - - if (get_user(data, &cmap32->red) || - put_user(compat_ptr(data), &cmap->red) || - get_user(data, &cmap32->green) || - put_user(compat_ptr(data), &cmap->green) || - get_user(data, &cmap32->blue) || - put_user(compat_ptr(data), &cmap->blue) || - get_user(data, &cmap32->transp) || - put_user(compat_ptr(data), &cmap->transp)) - return -EFAULT; - - err = sys_ioctl(fd, cmd, (unsigned long) cmap); - - if (!err) { - if (copy_in_user(&cmap32->start, - &cmap->start, - 2 * sizeof(__u32))) - err = -EFAULT; - } - return err; -} - -static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, - struct fb_fix_screeninfo32 __user *fix32) -{ - __u32 data; - int err; - - err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); - - data = (__u32) (unsigned long) fix->smem_start; - err |= put_user(data, &fix32->smem_start); - - err |= put_user(fix->smem_len, &fix32->smem_len); - err |= put_user(fix->type, &fix32->type); - err |= put_user(fix->type_aux, &fix32->type_aux); - err |= put_user(fix->visual, &fix32->visual); - err |= put_user(fix->xpanstep, &fix32->xpanstep); - err |= put_user(fix->ypanstep, &fix32->ypanstep); - err |= put_user(fix->ywrapstep, &fix32->ywrapstep); - err |= put_user(fix->line_length, &fix32->line_length); - - data = (__u32) (unsigned long) fix->mmio_start; - err |= put_user(data, &fix32->mmio_start); - - err |= put_user(fix->mmio_len, &fix32->mmio_len); - err |= put_user(fix->accel, &fix32->accel); - err |= copy_to_user(fix32->reserved, fix->reserved, - sizeof(fix->reserved)); - - return err; -} - -static int fb_get_fscreeninfo(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - struct fb_fix_screeninfo fix; - struct fb_fix_screeninfo32 __user *fix32; - int err; - - fix32 = compat_ptr(arg); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long) &fix); - set_fs(old_fs); - - if (!err) - err = do_fscreeninfo_to_user(&fix, fix32); - - return err; -} - -static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int err; - - switch (cmd) { - case FBIOGET_FSCREENINFO: - err = fb_get_fscreeninfo(fd,cmd, arg); - break; - - case FBIOGETCMAP: - case FBIOPUTCMAP: - err = fb_getput_cmap(fd, cmd, arg); - break; - - default: - do { - static int count; - if (++count <= 20) - printk("%s: Unknown fb ioctl cmd fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } while(0); - err = -ENOSYS; - break; - }; - - return err; -} - static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); @@ -2953,10 +2813,7 @@ HANDLE_IOCTL(BLKGETSIZE, w_long) HANDLE_IOCTL(0x1260, broken_blkgetsize) HANDLE_IOCTL(BLKFRAGET, w_long) HANDLE_IOCTL(BLKSECTGET, w_long) -HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans) -HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans) HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index 4c63c2963019..2209ad3499a3 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -56,13 +56,6 @@ ULONG_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) -/* Big F */ -COMPATIBLE_IOCTL(FBIOBLANK) -COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) -COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) -COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) /* Little f */ COMPATIBLE_IOCTL(FIOCLEX) COMPATIBLE_IOCTL(FIONCLEX) -- cgit v1.2.3 From 4e5314b56a7ea11c7a5f2b8418992b2f49648a25 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:22 -0800 Subject: [PATCH] md: better handling of readerrors with raid5. This patch changes the behaviour of raid5 when it gets a read error. Instead of just failing the device, it tried to find out what should have been there, and writes it over the bad block. For some media-errors, this has a reasonable chance of fixing the error. If the write succeeds, and a subsequent read succeeds as well, raid5 decided the address is OK and conitnues. Instead of failing a drive on read-error, we attempt to re-write the block, and then re-read. If that all works, we allow the device to remain in the array. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 61 ++++++++++++++++++++++++++++++++++++++++++---- include/linux/raid/raid5.h | 2 ++ 2 files changed, 58 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 1223e98ecd70..8cf1ae8b8a71 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -349,7 +349,7 @@ static void shrink_stripes(raid5_conf_t *conf) conf->slab_cache = NULL; } -static int raid5_end_read_request (struct bio * bi, unsigned int bytes_done, +static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, int error) { struct stripe_head *sh = bi->bi_private; @@ -401,10 +401,27 @@ static int raid5_end_read_request (struct bio * bi, unsigned int bytes_done, } #else set_bit(R5_UPTODATE, &sh->dev[i].flags); -#endif +#endif + if (test_bit(R5_ReadError, &sh->dev[i].flags)) { + printk("R5: read error corrected!!\n"); + clear_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReWrite, &sh->dev[i].flags); + } } else { - md_error(conf->mddev, conf->disks[i].rdev); clear_bit(R5_UPTODATE, &sh->dev[i].flags); + if (conf->mddev->degraded) { + printk("R5: read error not correctable.\n"); + clear_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReWrite, &sh->dev[i].flags); + md_error(conf->mddev, conf->disks[i].rdev); + } else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) { + /* Oh, no!!! */ + printk("R5: read error NOT corrected!!\n"); + clear_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReWrite, &sh->dev[i].flags); + md_error(conf->mddev, conf->disks[i].rdev); + } else + set_bit(R5_ReadError, &sh->dev[i].flags); } rdev_dec_pending(conf->disks[i].rdev, conf->mddev); #if 0 @@ -966,6 +983,12 @@ static void handle_stripe(struct stripe_head *sh) if (dev->written) written++; rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ if (!rdev || !rdev->in_sync) { + /* The ReadError flag wil just be confusing now */ + clear_bit(R5_ReadError, &dev->flags); + clear_bit(R5_ReWrite, &dev->flags); + } + if (!rdev || !rdev->in_sync + || test_bit(R5_ReadError, &dev->flags)) { failed++; failed_num = i; } else @@ -980,6 +1003,14 @@ static void handle_stripe(struct stripe_head *sh) if (failed > 1 && to_read+to_write+written) { for (i=disks; i--; ) { int bitmap_end = 0; + + if (test_bit(R5_ReadError, &sh->dev[i].flags)) { + mdk_rdev_t *rdev = conf->disks[i].rdev; + if (rdev && rdev->in_sync) + /* multiple read failures in one stripe */ + md_error(conf->mddev, rdev); + } + spin_lock_irq(&conf->device_lock); /* fail all writes first */ bi = sh->dev[i].towrite; @@ -1015,7 +1046,8 @@ static void handle_stripe(struct stripe_head *sh) } /* fail any reads if this device is non-operational */ - if (!test_bit(R5_Insync, &sh->dev[i].flags)) { + if (!test_bit(R5_Insync, &sh->dev[i].flags) || + test_bit(R5_ReadError, &sh->dev[i].flags)) { bi = sh->dev[i].toread; sh->dev[i].toread = NULL; if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) @@ -1274,7 +1306,26 @@ static void handle_stripe(struct stripe_head *sh) md_done_sync(conf->mddev, STRIPE_SECTORS,1); clear_bit(STRIPE_SYNCING, &sh->state); } - + + /* If the failed drive is just a ReadError, then we might need to progress + * the repair/check process + */ + if (failed == 1 && test_bit(R5_ReadError, &sh->dev[failed_num].flags) + && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags) + && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags) + ) { + dev = &sh->dev[failed_num]; + if (!test_bit(R5_ReWrite, &dev->flags)) { + set_bit(R5_Wantwrite, &dev->flags); + set_bit(R5_ReWrite, &dev->flags); + set_bit(R5_LOCKED, &dev->flags); + } else { + /* let's read it back */ + set_bit(R5_Wantread, &dev->flags); + set_bit(R5_LOCKED, &dev->flags); + } + } + spin_unlock(&sh->lock); while ((bi=return_bi)) { diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 176fc653c284..f025ba6fb14c 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -154,6 +154,8 @@ struct stripe_head { #define R5_Wantwrite 5 #define R5_Syncio 6 /* this io need to be accounted as resync io */ #define R5_Overlap 7 /* There is a pending overlapping request on this block */ +#define R5_ReadError 8 /* seen a read error here recently */ +#define R5_ReWrite 9 /* have tried to over-write the readerror */ /* * Write method -- cgit v1.2.3 From eae1701fbd264cfc7efbaf7cd4cd999760070e27 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:23 -0800 Subject: [PATCH] md: initial sysfs support for md Start using kobjects in mddevs, and provide a couple of simple attributes (level and disks). Attributes live in /sys/block/mdX/md/attr-name Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/raid/md_k.h | 2 ++ 2 files changed, 87 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ecf51ee596f..a68ad8547325 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -181,7 +181,7 @@ static void mddev_put(mddev_t *mddev) if (!mddev->raid_disks && list_empty(&mddev->disks)) { list_del(&mddev->all_mddevs); blk_put_queue(mddev->queue); - kfree(mddev); + kobject_unregister(&mddev->kobj); } spin_unlock(&all_mddevs_lock); } @@ -1551,6 +1551,85 @@ static void analyze_sbs(mddev_t * mddev) } +struct md_sysfs_entry { + struct attribute attr; + ssize_t (*show)(mddev_t *, char *); + ssize_t (*store)(mddev_t *, const char *, size_t); +}; + +static ssize_t +md_show_level(mddev_t *mddev, char *page) +{ + mdk_personality_t *p = mddev->pers; + if (p == NULL) + return 0; + if (mddev->level >= 0) + return sprintf(page, "RAID-%d\n", mddev->level); + else + return sprintf(page, "%s\n", p->name); +} + +static struct md_sysfs_entry md_level = { + .attr = {.name = "level", .mode = S_IRUGO }, + .show = md_show_level, +}; + +static ssize_t +md_show_rdisks(mddev_t *mddev, char *page) +{ + return sprintf(page, "%d\n", mddev->raid_disks); +} + +static struct md_sysfs_entry md_raid_disks = { + .attr = {.name = "raid_disks", .mode = S_IRUGO }, + .show = md_show_rdisks, +}; + +static struct attribute *md_default_attrs[] = { + &md_level.attr, + &md_raid_disks.attr, + NULL, +}; + +static ssize_t +md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); + mddev_t *mddev = container_of(kobj, struct mddev_s, kobj); + + if (!entry->show) + return -EIO; + return entry->show(mddev, page); +} + +static ssize_t +md_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); + mddev_t *mddev = container_of(kobj, struct mddev_s, kobj); + + if (!entry->store) + return -EIO; + return entry->store(mddev, page, length); +} + +static void md_free(struct kobject *ko) +{ + mddev_t *mddev = container_of(ko, mddev_t, kobj); + kfree(mddev); +} + +static struct sysfs_ops md_sysfs_ops = { + .show = md_attr_show, + .store = md_attr_store, +}; +static struct kobj_type md_ktype = { + .release = md_free, + .sysfs_ops = &md_sysfs_ops, + .default_attrs = md_default_attrs, +}; + int mdp_major = 0; static struct kobject *md_probe(dev_t dev, int *part, void *data) @@ -1592,6 +1671,11 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) add_disk(disk); mddev->gendisk = disk; up(&disks_sem); + mddev->kobj.parent = kobject_get(&disk->kobj); + mddev->kobj.k_name = NULL; + snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); + mddev->kobj.ktype = &md_ktype; + kobject_register(&mddev->kobj); return NULL; } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index ebce949b1443..a9b0e47a3d04 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -148,6 +148,8 @@ struct mddev_s struct gendisk *gendisk; + struct kobject kobj; + /* Superblock information */ int major_version, minor_version, -- cgit v1.2.3 From 86e6ffdd243a06663713e637ee683fb27dce8e0c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:24 -0800 Subject: [PATCH] md: extend md sysfs support to component devices. Each device in an md array how has a corresponding /sys/block/mdX/md/devNN/ directory which can contain attributes. Currently there is only 'state' which summarises the state, nd 'super' which has a copy of the superblock, and 'block' which is a symlink to the block device. Also, /sys/block/mdX/md/rdNN represents slot 'NN' in the array, and is a symlink to the relevant 'devNN'. Obviously spare devices do not have a slot in the array, and so don't have such a symlink. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 168 +++++++++++++++++++++++++++++++++++++++++++--- include/linux/raid/md_k.h | 2 + 2 files changed, 162 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index a68ad8547325..74520b50c307 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -711,6 +711,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) */ int i; int active=0, working=0,failed=0,spare=0,nr_disks=0; + unsigned int fixdesc=0; rdev->sb_size = MD_SB_BYTES; @@ -758,16 +759,28 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->disks[0].state = (1<raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) - rdev2->desc_nr = rdev2->raid_disk; + desc_nr = rdev2->raid_disk; else - rdev2->desc_nr = next_spare++; + desc_nr = next_spare++; + if (desc_nr != rdev2->desc_nr) { + fixdesc |= (1 << desc_nr); + rdev2->desc_nr = desc_nr; + if (rdev2->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev2->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + } + sysfs_remove_link(&rdev2->kobj, "block"); + kobject_del(&rdev2->kobj); + } d = &sb->disks[rdev2->desc_nr]; nr_disks++; d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); - if (rdev2->raid_disk >= 0 && rdev->in_sync && !rdev2->faulty) + if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ @@ -787,7 +800,22 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) if (test_bit(WriteMostly, &rdev2->flags)) d->state |= (1<desc_nr)) { + snprintf(rdev2->kobj.name, KOBJ_NAME_LEN, "dev%d", + rdev2->desc_nr); + kobject_add(&rdev2->kobj); + sysfs_create_link(&rdev2->kobj, + &rdev2->bdev->bd_disk->kobj, + "block"); + if (rdev2->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev2->raid_disk); + sysfs_create_link(&mddev->kobj, + &rdev2->kobj, nm); + } + } /* now set the "removed" and "faulty" bits on any missing devices */ for (i=0 ; i < mddev->raid_disks ; i++) { mdp_disk_t *d = &sb->disks[i]; @@ -1147,6 +1175,13 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; printk(KERN_INFO "md: bind<%s>\n", bdevname(rdev->bdev,b)); + + rdev->kobj.k_name = NULL; + snprintf(rdev->kobj.name, KOBJ_NAME_LEN, "dev%d", rdev->desc_nr); + rdev->kobj.parent = kobject_get(&mddev->kobj); + kobject_add(&rdev->kobj); + + sysfs_create_link(&rdev->kobj, &rdev->bdev->bd_disk->kobj, "block"); return 0; } @@ -1160,6 +1195,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) list_del_init(&rdev->same_set); printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); rdev->mddev = NULL; + sysfs_remove_link(&rdev->kobj, "block"); + kobject_del(&rdev->kobj); } /* @@ -1215,7 +1252,7 @@ static void export_rdev(mdk_rdev_t * rdev) md_autodetect_dev(rdev->bdev->bd_dev); #endif unlock_rdev(rdev); - kfree(rdev); + kobject_put(&rdev->kobj); } static void kick_rdev_from_array(mdk_rdev_t * rdev) @@ -1414,6 +1451,94 @@ repeat: } +struct rdev_sysfs_entry { + struct attribute attr; + ssize_t (*show)(mdk_rdev_t *, char *); + ssize_t (*store)(mdk_rdev_t *, const char *, size_t); +}; + +static ssize_t +rdev_show_state(mdk_rdev_t *rdev, char *page) +{ + char *sep = ""; + int len=0; + + if (rdev->faulty) { + len+= sprintf(page+len, "%sfaulty",sep); + sep = ","; + } + if (rdev->in_sync) { + len += sprintf(page+len, "%sin_sync",sep); + sep = ","; + } + if (!rdev->faulty && !rdev->in_sync) { + len += sprintf(page+len, "%sspare", sep); + sep = ","; + } + return len+sprintf(page+len, "\n"); +} + +static struct rdev_sysfs_entry rdev_state = { + .attr = {.name = "state", .mode = S_IRUGO }, + .show = rdev_show_state, +}; + +static ssize_t +rdev_show_super(mdk_rdev_t *rdev, char *page) +{ + if (rdev->sb_loaded && rdev->sb_size) { + memcpy(page, page_address(rdev->sb_page), rdev->sb_size); + return rdev->sb_size; + } else + return 0; +} +static struct rdev_sysfs_entry rdev_super = { + .attr = {.name = "super", .mode = S_IRUGO }, + .show = rdev_show_super, +}; +static struct attribute *rdev_default_attrs[] = { + &rdev_state.attr, + &rdev_super.attr, + NULL, +}; +static ssize_t +rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); + mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); + + if (!entry->show) + return -EIO; + return entry->show(rdev, page); +} + +static ssize_t +rdev_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); + mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); + + if (!entry->store) + return -EIO; + return entry->store(rdev, page, length); +} + +static void rdev_free(struct kobject *ko) +{ + mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj); + kfree(rdev); +} +static struct sysfs_ops rdev_sysfs_ops = { + .show = rdev_attr_show, + .store = rdev_attr_store, +}; +static struct kobj_type rdev_ktype = { + .release = rdev_free, + .sysfs_ops = &rdev_sysfs_ops, + .default_attrs = rdev_default_attrs, +}; + /* * Import a device. If 'super_format' >= 0, then sanity check the superblock * @@ -1445,6 +1570,10 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi if (err) goto abort_free; + rdev->kobj.parent = NULL; + rdev->kobj.ktype = &rdev_ktype; + kobject_init(&rdev->kobj); + rdev->desc_nr = -1; rdev->faulty = 0; rdev->in_sync = 0; @@ -1820,6 +1949,13 @@ static int do_md_run(mddev_t * mddev) mddev->safemode_timer.data = (unsigned long) mddev; mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */ mddev->in_sync = 1; + + ITERATE_RDEV(mddev,rdev,tmp) + if (rdev->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); + } set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); @@ -1941,9 +2077,18 @@ static int do_md_stop(mddev_t * mddev, int ro) * Free resources if final stop */ if (!ro) { + mdk_rdev_t *rdev; + struct list_head *tmp; struct gendisk *disk; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); + ITERATE_RDEV(mddev,rdev,tmp) + if (rdev->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + } + export_array(mddev); mddev->array_size = 0; @@ -3962,17 +4107,24 @@ void md_check_recovery(mddev_t *mddev) if (rdev->raid_disk >= 0 && (rdev->faulty || ! rdev->in_sync) && atomic_read(&rdev->nr_pending)==0) { - if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) + if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { + char nm[20]; + sprintf(nm,"rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); rdev->raid_disk = -1; + } } if (mddev->degraded) { ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 && !rdev->faulty) { - if (mddev->pers->hot_add_disk(mddev,rdev)) + if (mddev->pers->hot_add_disk(mddev,rdev)) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); spares++; - else + } else break; } } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index a9b0e47a3d04..d1dad32ebe07 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -105,6 +105,8 @@ struct mdk_rdev_s int sb_size; /* bytes in the superblock */ int preferred_minor; /* autorun support */ + struct kobject kobj; + /* A device can be in one of three states based on two flags: * Not working: faulty==1 in_sync==0 * Fully working: faulty==0 in_sync==1 -- cgit v1.2.3 From 3f294f4fb6f2ba887b717674da26c21f3d57f3fc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:25 -0800 Subject: [PATCH] md: add kobject/sysfs support to raid5 /sys/block/mdX/md/raid5/ contains raid5-related attributes. Currently stripe_cache_size is number of entries in stripe cache, and is settable. stripe_cache_active is number of active entries, and in only readable. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 183 +++++++++++++++++++++++++++++++++++++-------- include/linux/raid/raid5.h | 1 + 2 files changed, 152 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 8cf1ae8b8a71..121fbaa9ed59 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -293,9 +293,31 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector return sh; } -static int grow_stripes(raid5_conf_t *conf, int num) +static int grow_one_stripe(raid5_conf_t *conf) { struct stripe_head *sh; + sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); + if (!sh) + return 0; + memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); + sh->raid_conf = conf; + spin_lock_init(&sh->lock); + + if (grow_buffers(sh, conf->raid_disks)) { + shrink_buffers(sh, conf->raid_disks); + kmem_cache_free(conf->slab_cache, sh); + return 0; + } + /* we just created an active stripe so... */ + atomic_set(&sh->count, 1); + atomic_inc(&conf->active_stripes); + INIT_LIST_HEAD(&sh->lru); + release_stripe(sh); + return 1; +} + +static int grow_stripes(raid5_conf_t *conf, int num) +{ kmem_cache_t *sc; int devs = conf->raid_disks; @@ -308,43 +330,34 @@ static int grow_stripes(raid5_conf_t *conf, int num) return 1; conf->slab_cache = sc; while (num--) { - sh = kmem_cache_alloc(sc, GFP_KERNEL); - if (!sh) - return 1; - memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); - sh->raid_conf = conf; - spin_lock_init(&sh->lock); - - if (grow_buffers(sh, conf->raid_disks)) { - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(sc, sh); + if (!grow_one_stripe(conf)) return 1; - } - /* we just created an active stripe so... */ - atomic_set(&sh->count, 1); - atomic_inc(&conf->active_stripes); - INIT_LIST_HEAD(&sh->lru); - release_stripe(sh); } return 0; } -static void shrink_stripes(raid5_conf_t *conf) +static int drop_one_stripe(raid5_conf_t *conf) { struct stripe_head *sh; - while (1) { - spin_lock_irq(&conf->device_lock); - sh = get_free_stripe(conf); - spin_unlock_irq(&conf->device_lock); - if (!sh) - break; - if (atomic_read(&sh->count)) - BUG(); - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(conf->slab_cache, sh); - atomic_dec(&conf->active_stripes); - } + spin_lock_irq(&conf->device_lock); + sh = get_free_stripe(conf); + spin_unlock_irq(&conf->device_lock); + if (!sh) + return 0; + if (atomic_read(&sh->count)) + BUG(); + shrink_buffers(sh, conf->raid_disks); + kmem_cache_free(conf->slab_cache, sh); + atomic_dec(&conf->active_stripes); + return 1; +} + +static void shrink_stripes(raid5_conf_t *conf) +{ + while (drop_one_stripe(conf)) + ; + kmem_cache_destroy(conf->slab_cache); conf->slab_cache = NULL; } @@ -1714,6 +1727,108 @@ static void raid5d (mddev_t *mddev) PRINTK("--- raid5d inactive\n"); } +struct raid5_sysfs_entry { + struct attribute attr; + ssize_t (*show)(raid5_conf_t *, char *); + ssize_t (*store)(raid5_conf_t *, const char *, ssize_t); +}; + +static ssize_t +raid5_show_stripe_cache_size(raid5_conf_t *conf, char *page) +{ + return sprintf(page, "%d\n", conf->max_nr_stripes); +} + +static ssize_t +raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len) +{ + char *end; + int new; + if (len >= PAGE_SIZE) + return -EINVAL; + + new = simple_strtoul(page, &end, 10); + if (!*page || (*end && *end != '\n') ) + return -EINVAL; + if (new <= 16 || new > 32768) + return -EINVAL; + while (new < conf->max_nr_stripes) { + if (drop_one_stripe(conf)) + conf->max_nr_stripes--; + else + break; + } + while (new > conf->max_nr_stripes) { + if (grow_one_stripe(conf)) + conf->max_nr_stripes++; + else break; + } + return len; +} +static struct raid5_sysfs_entry raid5_stripecache_size = { + .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR }, + .show = raid5_show_stripe_cache_size, + .store = raid5_store_stripe_cache_size, +}; + +static ssize_t +raid5_show_stripe_cache_active(raid5_conf_t *conf, char *page) +{ + return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); +} + +static struct raid5_sysfs_entry raid5_stripecache_active = { + .attr = {.name = "stripe_cache_active", .mode = S_IRUGO}, + .show = raid5_show_stripe_cache_active, +}; + +static struct attribute *raid5_default_attrs[] = { + &raid5_stripecache_size.attr, + &raid5_stripecache_active.attr, + NULL, +}; + +static ssize_t +raid5_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); + raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); + + if (!entry->show) + return -EIO; + return entry->show(conf, page); +} + +static ssize_t +raid5_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); + raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); + + if (!entry->store) + return -EIO; + return entry->store(conf, page, length); +} + +static void raid5_free(struct kobject *ko) +{ + raid5_conf_t *conf = container_of(ko, raid5_conf_t, kobj); + kfree(conf); +} + + +static struct sysfs_ops raid5_sysfs_ops = { + .show = raid5_attr_show, + .store = raid5_attr_store, +}; + +static struct kobj_type raid5_ktype = { + .release = raid5_free, + .sysfs_ops = &raid5_sysfs_ops, + .default_attrs = raid5_default_attrs, +}; + static int run(mddev_t *mddev) { raid5_conf_t *conf; @@ -1855,6 +1970,10 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + } /* Ok, everything is just fine now */ + conf->kobj.parent = kobject_get(&mddev->kobj); + strcpy(conf->kobj.name, "raid5"); + conf->kobj.ktype = &raid5_ktype; + kobject_register(&conf->kobj); if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; @@ -1879,7 +1998,7 @@ abort: -static int stop (mddev_t *mddev) +static int stop(mddev_t *mddev) { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; @@ -1888,7 +2007,7 @@ static int stop (mddev_t *mddev) shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ - kfree(conf); + kobject_unregister(&conf->kobj); mddev->private = NULL; return 0; } diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index f025ba6fb14c..5f4e945c8083 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -228,6 +228,7 @@ struct raid5_private_data { * Cleared when a sync completes. */ + struct kobject kobj; /* * Free stripes pool */ -- cgit v1.2.3 From 24dd469d728dae07f40c5d79ea6dedd38cdf1a30 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:26 -0800 Subject: [PATCH] md: allow a manual resync with md You can trigger a 'check' with echo check > /sys/block/mdX/md/scan_mode or a check-and-repair errors with echo repair > /sys/block/mdX/md/scan_mode and read the current state from the same file. Note: personalities need to know the different between 'check' and 'repair', but don't yet. Until they do, 'check' will be the same as 'repair' and will just do a normal resync pass. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 77 +++++++++++++++++++++++++++++++++++++++++------ include/linux/raid/md_k.h | 4 +++ 2 files changed, 72 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index 74520b50c307..37400873b879 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1714,9 +1714,60 @@ static struct md_sysfs_entry md_raid_disks = { .show = md_show_rdisks, }; +static ssize_t +md_show_scan(mddev_t *mddev, char *page) +{ + char *type = "none"; + if (mddev->recovery & + ((1<recovery & (1<recovery)) + type = "resync"; + else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) + type = "check"; + else + type = "repair"; + } else + type = "recover"; + } + return sprintf(page, "%s\n", type); +} + +static ssize_t +md_store_scan(mddev_t *mddev, const char *page, size_t len) +{ + int canscan=0; + if (mddev->recovery & + ((1<reconfig_sem); + if (mddev->pers && mddev->pers->sync_request) + canscan=1; + up(&mddev->reconfig_sem); + if (!canscan) + return -EINVAL; + + if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0) + set_bit(MD_RECOVERY_CHECK, &mddev->recovery); + else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0) + return -EINVAL; + set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); + set_bit(MD_RECOVERY_SYNC, &mddev->recovery); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); + return len; +} + +static struct md_sysfs_entry md_scan_mode = { + .attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR }, + .show = md_show_scan, + .store = md_store_scan, +}; + static struct attribute *md_default_attrs[] = { &md_level.attr, &md_raid_disks.attr, + &md_scan_mode.attr, NULL, }; @@ -3855,7 +3906,8 @@ static void md_do_sync(mddev_t *mddev) is_mddev_idle(mddev); /* this also initializes IO event counters */ /* we don't use the checkpoint if there's a bitmap */ - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap) + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap + && ! test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) j = mddev->recovery_cp; else j = 0; @@ -4093,9 +4145,13 @@ void md_check_recovery(mddev_t *mddev) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); goto unlock; } - if (mddev->recovery) - /* probably just the RECOVERY_NEEDED flag */ - mddev->recovery = 0; + /* Clear some bits that don't mean anything, but + * might be left set + */ + clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + clear_bit(MD_RECOVERY_ERR, &mddev->recovery); + clear_bit(MD_RECOVERY_INTR, &mddev->recovery); + clear_bit(MD_RECOVERY_DONE, &mddev->recovery); /* no recovery is running. * remove any failed drives, then @@ -4129,14 +4185,17 @@ void md_check_recovery(mddev_t *mddev) } } - if (!spares && (mddev->recovery_cp == MaxSector )) { - /* nothing we can do ... */ + if (spares) { + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + } else if (mddev->recovery_cp < MaxSector) { + set_bit(MD_RECOVERY_SYNC, &mddev->recovery); + } else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + /* nothing to be done ... */ goto unlock; - } + if (mddev->pers->sync_request) { set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - if (!spares) - set_bit(MD_RECOVERY_SYNC, &mddev->recovery); if (spares && mddev->bitmap && ! mddev->bitmap->file) { /* We are adding a device or devices to an array * which has the bitmap stored on all devices. diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index d1dad32ebe07..efd04dca0abd 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -182,6 +182,8 @@ struct mddev_s * ERR: and IO error was detected - abort the resync/recovery * INTR: someone requested a (clean) early abort. * DONE: thread is done and is waiting to be reaped + * REQUEST: user-space has requested a sync (used with SYNC) + * CHECK: user-space request for for check-only, no repair */ #define MD_RECOVERY_RUNNING 0 #define MD_RECOVERY_SYNC 1 @@ -189,6 +191,8 @@ struct mddev_s #define MD_RECOVERY_INTR 3 #define MD_RECOVERY_DONE 4 #define MD_RECOVERY_NEEDED 5 +#define MD_RECOVERY_REQUESTED 6 +#define MD_RECOVERY_CHECK 7 unsigned long recovery; int in_sync; /* know to not need resync */ -- cgit v1.2.3 From 9d88883e68f404d5581bd391713ceef470ea53a9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:26 -0800 Subject: [PATCH] md: teach raid5 the difference between 'check' and 'repair'. With this, raid5 can be asked to check parity without repairing it. It also keeps a count of the number of incorrect parity blocks found (mismatches) and reports them through sysfs. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 18 ++++++++++++++++-- drivers/md/raid5.c | 5 +++++ include/linux/raid/md_k.h | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index 37400873b879..e58d61d9f31b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1758,16 +1758,29 @@ md_store_scan(mddev_t *mddev, const char *page, size_t len) return len; } +static ssize_t +md_show_mismatch(mddev_t *mddev, char *page) +{ + return sprintf(page, "%llu\n", + (unsigned long long) mddev->resync_mismatches); +} + static struct md_sysfs_entry md_scan_mode = { .attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR }, .show = md_show_scan, .store = md_store_scan, }; +static struct md_sysfs_entry md_mismatches = { + .attr = {.name = "mismatch_cnt", .mode = S_IRUGO }, + .show = md_show_mismatch, +}; + static struct attribute *md_default_attrs[] = { &md_level.attr, &md_raid_disks.attr, &md_scan_mode.attr, + &md_mismatches.attr, NULL, }; @@ -3888,12 +3901,13 @@ static void md_do_sync(mddev_t *mddev) } } while (mddev->curr_resync < 2); - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { /* resync follows the size requested by the personality, * which defaults to physical size, but can be virtual size */ max_sectors = mddev->resync_max_sectors; - else + mddev->resync_mismatches = 0; + } else /* recovery follows the physical size of devices */ max_sectors = mddev->size << 1; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 121fbaa9ed59..ce154553aca5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1292,6 +1292,11 @@ static void handle_stripe(struct stripe_head *sh) !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) { /* parity is correct (on disc, not in buffer any more) */ set_bit(STRIPE_INSYNC, &sh->state); + } else { + conf->mddev->resync_mismatches += STRIPE_SECTORS; + if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) + /* don't try to repair!! */ + set_bit(STRIPE_INSYNC, &sh->state); } } if (!test_bit(STRIPE_INSYNC, &sh->state)) { diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index efd04dca0abd..cb8b44d1588b 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -175,6 +175,10 @@ struct mddev_s sector_t resync_mark_cnt;/* blocks written at resync_mark */ sector_t resync_max_sectors; /* may be set by personality */ + + sector_t resync_mismatches; /* count of sectors where + * parity/replica mismatch found + */ /* recovery/resync flags * NEEDED: we might need to start a resync/recover * RUNNING: a thread is running, or about to be started -- cgit v1.2.3 From 007583c9253fed363a0bd71b039e9b40a0f6855e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:30 -0800 Subject: [PATCH] md: change raid5 sysfs attribute to not create a new directory There isn't really a need for raid5 attributes to be an a subdirectory, so this patch moves them from /sys/block/mdX/md/raid5/attribute to /sys/block/mdX/md/attribute This suggests that all md personalities should co-operate about namespace usage, but that shouldn't be a problem. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 6 ---- drivers/md/raid5.c | 72 ++++++++++------------------------------------ include/linux/raid/md_k.h | 7 +++++ include/linux/raid/raid5.h | 1 - 4 files changed, 22 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index 013f2f27589c..3db5c3513072 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1683,12 +1683,6 @@ static void analyze_sbs(mddev_t * mddev) } -struct md_sysfs_entry { - struct attribute attr; - ssize_t (*show)(mddev_t *, char *); - ssize_t (*store)(mddev_t *, const char *, size_t); -}; - static ssize_t md_show_level(mddev_t *mddev, char *page) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 246c9b1cc4a3..08a1620b9f8c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1732,21 +1732,17 @@ static void raid5d (mddev_t *mddev) PRINTK("--- raid5d inactive\n"); } -struct raid5_sysfs_entry { - struct attribute attr; - ssize_t (*show)(raid5_conf_t *, char *); - ssize_t (*store)(raid5_conf_t *, const char *, ssize_t); -}; - static ssize_t -raid5_show_stripe_cache_size(raid5_conf_t *conf, char *page) +raid5_show_stripe_cache_size(mddev_t *mddev, char *page) { + raid5_conf_t *conf = mddev_to_conf(mddev); return sprintf(page, "%d\n", conf->max_nr_stripes); } static ssize_t -raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len) +raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) { + raid5_conf_t *conf = mddev_to_conf(mddev); char *end; int new; if (len >= PAGE_SIZE) @@ -1770,68 +1766,33 @@ raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len) } return len; } -static struct raid5_sysfs_entry raid5_stripecache_size = { + +static struct md_sysfs_entry raid5_stripecache_size = { .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR }, .show = raid5_show_stripe_cache_size, .store = raid5_store_stripe_cache_size, }; static ssize_t -raid5_show_stripe_cache_active(raid5_conf_t *conf, char *page) +raid5_show_stripe_cache_active(mddev_t *mddev, char *page) { + raid5_conf_t *conf = mddev_to_conf(mddev); return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); } -static struct raid5_sysfs_entry raid5_stripecache_active = { +static struct md_sysfs_entry raid5_stripecache_active = { .attr = {.name = "stripe_cache_active", .mode = S_IRUGO}, .show = raid5_show_stripe_cache_active, }; -static struct attribute *raid5_default_attrs[] = { +static struct attribute *raid5_attrs[] = { &raid5_stripecache_size.attr, &raid5_stripecache_active.attr, NULL, }; - -static ssize_t -raid5_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); - raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); - - if (!entry->show) - return -EIO; - return entry->show(conf, page); -} - -static ssize_t -raid5_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); - raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); - - if (!entry->store) - return -EIO; - return entry->store(conf, page, length); -} - -static void raid5_free(struct kobject *ko) -{ - raid5_conf_t *conf = container_of(ko, raid5_conf_t, kobj); - kfree(conf); -} - - -static struct sysfs_ops raid5_sysfs_ops = { - .show = raid5_attr_show, - .store = raid5_attr_store, -}; - -static struct kobj_type raid5_ktype = { - .release = raid5_free, - .sysfs_ops = &raid5_sysfs_ops, - .default_attrs = raid5_default_attrs, +static struct attribute_group raid5_attrs_group = { + .name = NULL, + .attrs = raid5_attrs, }; static int run(mddev_t *mddev) @@ -1975,10 +1936,7 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + } /* Ok, everything is just fine now */ - conf->kobj.parent = &mddev->kobj; - strcpy(conf->kobj.name, "raid5"); - conf->kobj.ktype = &raid5_ktype; - kobject_register(&conf->kobj); + sysfs_create_group(&mddev->kobj, &raid5_attrs_group); if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; @@ -2012,7 +1970,7 @@ static int stop(mddev_t *mddev) shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ - kobject_unregister(&conf->kobj); + sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); mddev->private = NULL; return 0; } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index cb8b44d1588b..4169c11e5451 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -282,6 +282,13 @@ struct mdk_personality_s }; +struct md_sysfs_entry { + struct attribute attr; + ssize_t (*show)(mddev_t *, char *); + ssize_t (*store)(mddev_t *, const char *, size_t); +}; + + static inline char * mdname (mddev_t * mddev) { return mddev->gendisk ? mddev->gendisk->disk_name : "mdX"; diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 5f4e945c8083..f025ba6fb14c 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -228,7 +228,6 @@ struct raid5_private_data { * Cleared when a sync completes. */ - struct kobject kobj; /* * Free stripes pool */ -- cgit v1.2.3 From ba22dcbf106338a5c46d6979f9b19564faae3d49 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:31 -0800 Subject: [PATCH] md: improvements to raid5 handling of read errors Two refinements to the 'attempt-overwrite-on-read-error' mechanism. 1/ If the array is read-only, don't attempt an over-write. 2/ If there are more than max_nr_stripes read errors on a device with no success, fail the drive. This will make sure a dead drive will be eventually kicked even when we aren't trying to rewrite (which would normally kick a dead drive more quickly. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 + drivers/md/raid5.c | 25 +++++++++++++++++-------- include/linux/raid/md_k.h | 3 +++ 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index 3db5c3513072..3fb80397f8aa 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1582,6 +1582,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi rdev->in_sync = 0; rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); + atomic_set(&rdev->read_errors, 0); size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; if (!size) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 08a1620b9f8c..77610b98d4e0 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -420,21 +420,29 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); } + if (atomic_read(&conf->disks[i].rdev->read_errors)) + atomic_set(&conf->disks[i].rdev->read_errors, 0); } else { + int retry = 0; clear_bit(R5_UPTODATE, &sh->dev[i].flags); - if (conf->mddev->degraded) { + atomic_inc(&conf->disks[i].rdev->read_errors); + if (conf->mddev->degraded) printk("R5: read error not correctable.\n"); - clear_bit(R5_ReadError, &sh->dev[i].flags); - clear_bit(R5_ReWrite, &sh->dev[i].flags); - md_error(conf->mddev, conf->disks[i].rdev); - } else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) { + else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) /* Oh, no!!! */ printk("R5: read error NOT corrected!!\n"); + else if (atomic_read(&conf->disks[i].rdev->read_errors) + > conf->max_nr_stripes) + printk("raid5: Too many read errors, failing device.\n"); + else + retry = 1; + if (retry) + set_bit(R5_ReadError, &sh->dev[i].flags); + else { clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); md_error(conf->mddev, conf->disks[i].rdev); - } else - set_bit(R5_ReadError, &sh->dev[i].flags); + } } rdev_dec_pending(conf->disks[i].rdev, conf->mddev); #if 0 @@ -1328,7 +1336,8 @@ static void handle_stripe(struct stripe_head *sh) /* If the failed drive is just a ReadError, then we might need to progress * the repair/check process */ - if (failed == 1 && test_bit(R5_ReadError, &sh->dev[failed_num].flags) + if (failed == 1 && ! conf->mddev->ro && + test_bit(R5_ReadError, &sh->dev[failed_num].flags) && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags) && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags) ) { diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 4169c11e5451..200c69e34fc0 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -134,6 +134,9 @@ struct mdk_rdev_s * only maintained for arrays that * support hot removal */ + atomic_t read_errors; /* number of consecutive read errors that + * we have tried to ignore. + */ }; typedef struct mdk_personality_s mdk_personality_t; -- cgit v1.2.3 From b2d444d7ad975d555bb919601bcdc0e58975a40e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:31 -0800 Subject: [PATCH] md: convert 'faulty' and 'in_sync' fields to bits in 'flags' field This has the advantage of removing the confusion caused by 'rdev_t' and 'mddev_t' both having 'in_sync' fields. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 6 ++-- drivers/md/md.c | 92 +++++++++++++++++++++++------------------------ drivers/md/multipath.c | 23 ++++++------ drivers/md/raid1.c | 52 +++++++++++++-------------- drivers/md/raid10.c | 41 ++++++++++----------- drivers/md/raid5.c | 36 +++++++++---------- drivers/md/raid6main.c | 32 ++++++++--------- include/linux/raid/md_k.h | 8 ++--- 8 files changed, 146 insertions(+), 144 deletions(-) (limited to 'include') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index e59694bc5758..c5fa4c2a5af1 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -271,7 +271,8 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde return ERR_PTR(-ENOMEM); ITERATE_RDEV(mddev, rdev, tmp) { - if (! rdev->in_sync || rdev->faulty) + if (! test_bit(In_sync, &rdev->flags) + || test_bit(Faulty, &rdev->flags)) continue; target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512); @@ -291,7 +292,8 @@ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wai struct list_head *tmp; ITERATE_RDEV(mddev, rdev, tmp) - if (rdev->in_sync && !rdev->faulty) + if (test_bit(In_sync, &rdev->flags) + && !test_bit(Faulty, &rdev->flags)) md_super_write(mddev, rdev, (rdev->sb_offset<<1) + offset + page->index * (PAGE_SIZE/512), diff --git a/drivers/md/md.c b/drivers/md/md.c index 3fb80397f8aa..9dfa063d1c6a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -610,7 +610,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page); rdev->raid_disk = -1; - rdev->in_sync = 0; + rdev->flags = 0; if (mddev->raid_disks == 0) { mddev->major_version = 0; mddev->minor_version = sb->minor_version; @@ -671,21 +671,19 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) return 0; if (mddev->level != LEVEL_MULTIPATH) { - rdev->faulty = 0; - rdev->flags = 0; desc = sb->disks + rdev->desc_nr; if (desc->state & (1<faulty = 1; + set_bit(Faulty, &rdev->flags); else if (desc->state & (1<raid_disk < mddev->raid_disks) { - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); rdev->raid_disk = desc->raid_disk; } if (desc->state & (1<flags); } else /* MULTIPATH are always insync */ - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); return 0; } @@ -761,7 +759,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) ITERATE_RDEV(mddev,rdev2,tmp) { mdp_disk_t *d; int desc_nr; - if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) + if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) + && !test_bit(Faulty, &rdev2->flags)) desc_nr = rdev2->raid_disk; else desc_nr = next_spare++; @@ -780,14 +779,15 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); - if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) + if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) + && !test_bit(Faulty, &rdev2->flags)) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ - if (rdev2->faulty) { + if (test_bit(Faulty, &rdev2->flags)) { d->state = (1<in_sync) { + } else if (test_bit(In_sync, &rdev2->flags)) { d->state = (1<state |= (1<sb_page); rdev->raid_disk = -1; - rdev->in_sync = 0; + rdev->flags = 0; if (mddev->raid_disks == 0) { mddev->major_version = 1; mddev->patch_version = 0; @@ -1027,22 +1027,19 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); switch(role) { case 0xffff: /* spare */ - rdev->faulty = 0; break; case 0xfffe: /* faulty */ - rdev->faulty = 1; + set_bit(Faulty, &rdev->flags); break; default: - rdev->in_sync = 1; - rdev->faulty = 0; + set_bit(In_sync, &rdev->flags); rdev->raid_disk = role; break; } - rdev->flags = 0; if (sb->devflags & WriteMostly1) set_bit(WriteMostly, &rdev->flags); } else /* MULTIPATH are always insync */ - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); return 0; } @@ -1086,9 +1083,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) ITERATE_RDEV(mddev,rdev2,tmp) { i = rdev2->desc_nr; - if (rdev2->faulty) + if (test_bit(Faulty, &rdev2->flags)) sb->dev_roles[i] = cpu_to_le16(0xfffe); - else if (rdev2->in_sync) + else if (test_bit(In_sync, &rdev2->flags)) sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); else sb->dev_roles[i] = cpu_to_le16(0xffff); @@ -1327,7 +1324,8 @@ static void print_rdev(mdk_rdev_t *rdev) char b[BDEVNAME_SIZE]; printk(KERN_INFO "md: rdev %s, SZ:%08llu F:%d S:%d DN:%u\n", bdevname(rdev->bdev,b), (unsigned long long)rdev->size, - rdev->faulty, rdev->in_sync, rdev->desc_nr); + test_bit(Faulty, &rdev->flags), test_bit(In_sync, &rdev->flags), + rdev->desc_nr); if (rdev->sb_loaded) { printk(KERN_INFO "md: rdev superblock:\n"); print_sb((mdp_super_t*)page_address(rdev->sb_page)); @@ -1421,11 +1419,11 @@ repeat: ITERATE_RDEV(mddev,rdev,tmp) { char b[BDEVNAME_SIZE]; dprintk(KERN_INFO "md: "); - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) dprintk("(skipping faulty "); dprintk("%s ", bdevname(rdev->bdev,b)); - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { md_super_write(mddev,rdev, rdev->sb_offset<<1, rdev->sb_size, rdev->sb_page); @@ -1466,15 +1464,16 @@ rdev_show_state(mdk_rdev_t *rdev, char *page) char *sep = ""; int len=0; - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { len+= sprintf(page+len, "%sfaulty",sep); sep = ","; } - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { len += sprintf(page+len, "%sin_sync",sep); sep = ","; } - if (!rdev->faulty && !rdev->in_sync) { + if (!test_bit(Faulty, &rdev->flags) && + !test_bit(In_sync, &rdev->flags)) { len += sprintf(page+len, "%sspare", sep); sep = ","; } @@ -1578,8 +1577,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi kobject_init(&rdev->kobj); rdev->desc_nr = -1; - rdev->faulty = 0; - rdev->in_sync = 0; + rdev->flags = 0; rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); atomic_set(&rdev->read_errors, 0); @@ -1670,7 +1668,7 @@ static void analyze_sbs(mddev_t * mddev) if (mddev->level == LEVEL_MULTIPATH) { rdev->desc_nr = i++; rdev->raid_disk = rdev->desc_nr; - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); } } @@ -1939,7 +1937,7 @@ static int do_md_run(mddev_t * mddev) /* devices must have minimum size of one chunk */ ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) continue; if (rdev->size < chunk_size / 1024) { printk(KERN_WARNING @@ -1967,7 +1965,7 @@ static int do_md_run(mddev_t * mddev) * Also find largest hardsector size */ ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) continue; sync_blockdev(rdev->bdev); invalidate_bdev(rdev->bdev, 0); @@ -2304,7 +2302,7 @@ static int autostart_array(dev_t startdev) return err; } - if (start_rdev->faulty) { + if (test_bit(Faulty, &start_rdev->flags)) { printk(KERN_WARNING "md: can not autostart based on faulty %s!\n", bdevname(start_rdev->bdev,b)); @@ -2363,11 +2361,11 @@ static int get_array_info(mddev_t * mddev, void __user * arg) nr=working=active=failed=spare=0; ITERATE_RDEV(mddev,rdev,tmp) { nr++; - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) failed++; else { working++; - if (rdev->in_sync) + if (test_bit(In_sync, &rdev->flags)) active++; else spare++; @@ -2458,9 +2456,9 @@ static int get_disk_info(mddev_t * mddev, void __user * arg) info.minor = MINOR(rdev->bdev->bd_dev); info.raid_disk = rdev->raid_disk; info.state = 0; - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) info.state |= (1<in_sync) { + else if (test_bit(In_sync, &rdev->flags)) { info.state |= (1<saved_raid_disk = rdev->raid_disk; - rdev->in_sync = 0; /* just to be sure */ + clear_bit(In_sync, &rdev->flags); /* just to be sure */ if (info->state & (1<flags); @@ -2591,11 +2589,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) else rdev->raid_disk = -1; - rdev->faulty = 0; + rdev->flags = 0; + if (rdev->raid_disk < mddev->raid_disks) - rdev->in_sync = (info->state & (1<in_sync = 0; + if (info->state & (1<flags); if (info->state & (1<flags); @@ -2694,14 +2692,14 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) goto abort_export; } - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { printk(KERN_WARNING "md: can not hot-add faulty %s disk to %s!\n", bdevname(rdev->bdev,b), mdname(mddev)); err = -EINVAL; goto abort_export; } - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); rdev->desc_nr = -1; bind_rdev_to_array(rdev, mddev); @@ -3428,7 +3426,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) return; } - if (!rdev || rdev->faulty) + if (!rdev || test_bit(Faulty, &rdev->flags)) return; /* dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", @@ -3626,7 +3624,7 @@ static int md_seq_show(struct seq_file *seq, void *v) bdevname(rdev->bdev,b), rdev->desc_nr); if (test_bit(WriteMostly, &rdev->flags)) seq_printf(seq, "(W)"); - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { seq_printf(seq, "(F)"); continue; } else if (rdev->raid_disk < 0) @@ -4174,7 +4172,7 @@ void md_check_recovery(mddev_t *mddev) */ ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk >= 0 && - (rdev->faulty || ! rdev->in_sync) && + (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && atomic_read(&rdev->nr_pending)==0) { if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { char nm[20]; @@ -4187,7 +4185,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->degraded) { ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 - && !rdev->faulty) { + && !test_bit(Faulty, &rdev->flags)) { if (mddev->pers->hot_add_disk(mddev,rdev)) { char nm[20]; sprintf(nm, "rd%d", rdev->raid_disk); @@ -4347,7 +4345,7 @@ static void autostart_arrays(int part) if (IS_ERR(rdev)) continue; - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { MD_BUG(); continue; } diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index ae2c5fd6105d..145cdc5ad008 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -64,7 +64,7 @@ static int multipath_map (multipath_conf_t *conf) rcu_read_lock(); for (i = 0; i < disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && rdev->in_sync) { + if (rdev && test_bit(In_sync, &rdev->flags)) { atomic_inc(&rdev->nr_pending); rcu_read_unlock(); return i; @@ -140,7 +140,8 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) + && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -211,7 +212,7 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf (seq, "%s", conf->multipaths[i].rdev && - conf->multipaths[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->multipaths[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); } @@ -225,7 +226,7 @@ static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -265,10 +266,10 @@ static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) /* * Mark disk as unusable */ - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { char b[BDEVNAME_SIZE]; - rdev->in_sync = 0; - rdev->faulty = 1; + clear_bit(In_sync, &rdev->flags); + set_bit(Faulty, &rdev->flags); mddev->sb_dirty = 1; conf->working_disks--; printk(KERN_ALERT "multipath: IO failure on %s," @@ -298,7 +299,7 @@ static void print_multipath_conf (multipath_conf_t *conf) tmp = conf->multipaths + i; if (tmp->rdev) printk(" disk%d, o:%d, dev:%s\n", - i,!tmp->rdev->faulty, + i,!test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -330,7 +331,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) conf->working_disks++; rdev->raid_disk = path; - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); rcu_assign_pointer(p->rdev, rdev); found = 1; } @@ -350,7 +351,7 @@ static int multipath_remove_disk(mddev_t *mddev, int number) rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { printk(KERN_ERR "hot-remove-disk, slot %d is identified" " but is still operational!\n", number); err = -EBUSY; @@ -482,7 +483,7 @@ static int multipath_run (mddev_t *mddev) mddev->queue->max_sectors > (PAGE_SIZE>>9)) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); - if (!rdev->faulty) + if (!test_bit(Faulty, &rdev->flags)) conf->working_disks++; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f12fc288f25d..fb6b866c28f5 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -417,11 +417,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) new_disk = 0; for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); - !rdev || !rdev->in_sync + !rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags); rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) { - if (rdev && rdev->in_sync) + if (rdev && test_bit(In_sync, &rdev->flags)) wonly_disk = new_disk; if (new_disk == conf->raid_disks - 1) { @@ -435,11 +435,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) /* make sure the disk is operational */ for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); - !rdev || !rdev->in_sync || + !rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags); rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) { - if (rdev && rdev->in_sync) + if (rdev && test_bit(In_sync, &rdev->flags)) wonly_disk = new_disk; if (new_disk <= 0) @@ -477,7 +477,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) rdev = rcu_dereference(conf->mirrors[disk].rdev); if (!rdev || - !rdev->in_sync || + !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags)) continue; @@ -500,7 +500,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) if (!rdev) goto retry; atomic_inc(&rdev->nr_pending); - if (!rdev->in_sync) { + if (!test_bit(In_sync, &rdev->flags)) { /* cannot risk returning a device that failed * before we inc'ed nr_pending */ @@ -523,7 +523,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -557,7 +557,7 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -729,9 +729,9 @@ static int make_request(request_queue_t *q, struct bio * bio) rcu_read_lock(); for (i = 0; i < disks; i++) { if ((rdev=rcu_dereference(conf->mirrors[i].rdev)) != NULL && - !rdev->faulty) { + !test_bit(Faulty, &rdev->flags)) { atomic_inc(&rdev->nr_pending); - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { atomic_dec(&rdev->nr_pending); r1_bio->bios[i] = NULL; } else @@ -824,7 +824,7 @@ static void status(struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf(seq, "%s", conf->mirrors[i].rdev && - conf->mirrors[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); seq_printf(seq, "]"); } @@ -840,14 +840,14 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) * next level up know. * else mark the drive as failed */ - if (rdev->in_sync + if (test_bit(In_sync, &rdev->flags) && conf->working_disks == 1) /* * Don't fail the drive, act as though we were just a * normal single drive */ return; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { mddev->degraded++; conf->working_disks--; /* @@ -855,8 +855,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->in_sync = 0; - rdev->faulty = 1; + clear_bit(In_sync, &rdev->flags); + set_bit(Faulty, &rdev->flags); mddev->sb_dirty = 1; printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", @@ -881,7 +881,7 @@ static void print_conf(conf_t *conf) tmp = conf->mirrors + i; if (tmp->rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !tmp->rdev->in_sync, !tmp->rdev->faulty, + i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -913,11 +913,11 @@ static int raid1_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->mirrors + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { conf->working_disks++; mddev->degraded--; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } @@ -972,7 +972,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number) print_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -1282,11 +1282,11 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* make sure disk is operational */ wonly = disk; while (conf->mirrors[disk].rdev == NULL || - !conf->mirrors[disk].rdev->in_sync || + !test_bit(In_sync, &conf->mirrors[disk].rdev->flags) || test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags) ) { if (conf->mirrors[disk].rdev && - conf->mirrors[disk].rdev->in_sync) + test_bit(In_sync, &conf->mirrors[disk].rdev->flags)) wonly = disk; if (disk <= 0) disk = conf->raid_disks; @@ -1333,10 +1333,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio->bi_rw = READ; bio->bi_end_io = end_sync_read; } else if (conf->mirrors[i].rdev == NULL || - conf->mirrors[i].rdev->faulty) { + test_bit(Faulty, &conf->mirrors[i].rdev->flags)) { still_degraded = 1; continue; - } else if (!conf->mirrors[i].rdev->in_sync || + } else if (!test_bit(In_sync, &conf->mirrors[i].rdev->flags) || sector_nr + RESYNC_SECTORS > mddev->recovery_cp) { bio->bi_rw = WRITE; bio->bi_end_io = end_sync_write; @@ -1478,7 +1478,7 @@ static int run(mddev_t *mddev) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); disk->head_position = 0; - if (!rdev->faulty && rdev->in_sync) + if (!test_bit(Faulty, &rdev->flags) && test_bit(In_sync, &rdev->flags)) conf->working_disks++; } conf->raid_disks = mddev->raid_disks; @@ -1518,7 +1518,7 @@ static int run(mddev_t *mddev) */ for (j = 0; j < conf->raid_disks && (!conf->mirrors[j].rdev || - !conf->mirrors[j].rdev->in_sync) ; j++) + !test_bit(In_sync, &conf->mirrors[j].rdev->flags)) ; j++) /* nothing */; conf->last_used = j; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 26114f40bde6..867f06ae33d9 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -512,7 +512,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) disk = r10_bio->devs[slot].devnum; while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL || - !rdev->in_sync) { + !test_bit(In_sync, &rdev->flags)) { slot++; if (slot == conf->copies) { slot = 0; @@ -529,7 +529,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) slot = 0; disk = r10_bio->devs[slot].devnum; while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL || - !rdev->in_sync) { + !test_bit(In_sync, &rdev->flags)) { slot ++; if (slot == conf->copies) { disk = -1; @@ -549,7 +549,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL || - !rdev->in_sync) + !test_bit(In_sync, &rdev->flags)) continue; if (!atomic_read(&rdev->nr_pending)) { @@ -585,7 +585,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -616,7 +616,7 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -771,7 +771,7 @@ static int make_request(request_queue_t *q, struct bio * bio) int d = r10_bio->devs[i].devnum; mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev); if (rdev && - !rdev->faulty) { + !test_bit(Faulty, &rdev->flags)) { atomic_inc(&rdev->nr_pending); r10_bio->devs[i].bio = bio; } else @@ -826,7 +826,7 @@ static void status(struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf(seq, "%s", conf->mirrors[i].rdev && - conf->mirrors[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); seq_printf(seq, "]"); } @@ -841,7 +841,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) * next level up know. * else mark the drive as failed */ - if (rdev->in_sync + if (test_bit(In_sync, &rdev->flags) && conf->working_disks == 1) /* * Don't fail the drive, just return an IO error. @@ -851,7 +851,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) * really dead" tests... */ return; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { mddev->degraded++; conf->working_disks--; /* @@ -859,8 +859,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->in_sync = 0; - rdev->faulty = 1; + clear_bit(In_sync, &rdev->flags); + set_bit(Faulty, &rdev->flags); mddev->sb_dirty = 1; printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", @@ -885,7 +885,8 @@ static void print_conf(conf_t *conf) tmp = conf->mirrors + i; if (tmp->rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !tmp->rdev->in_sync, !tmp->rdev->faulty, + i, !test_bit(In_sync, &tmp->rdev->flags), + !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -938,11 +939,11 @@ static int raid10_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->mirrors + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { conf->working_disks++; mddev->degraded--; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } @@ -1000,7 +1001,7 @@ static int raid10_remove_disk(mddev_t *mddev, int number) print_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -1416,7 +1417,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (i=0 ; iraid_disks; i++) if (conf->mirrors[i].rdev && - !conf->mirrors[i].rdev->in_sync) { + !test_bit(In_sync, &conf->mirrors[i].rdev->flags)) { /* want to reconstruct this device */ r10bio_t *rb2 = r10_bio; @@ -1437,7 +1438,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (j=0; jcopies;j++) { int d = r10_bio->devs[j].devnum; if (conf->mirrors[d].rdev && - conf->mirrors[d].rdev->in_sync) { + test_bit(In_sync, &conf->mirrors[d].rdev->flags)) { /* This is where we read from */ bio = r10_bio->devs[0].bio; bio->bi_next = biolist; @@ -1513,7 +1514,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio = r10_bio->devs[i].bio; bio->bi_end_io = NULL; if (conf->mirrors[d].rdev == NULL || - conf->mirrors[d].rdev->faulty) + test_bit(Faulty, &conf->mirrors[d].rdev->flags)) continue; atomic_inc(&conf->mirrors[d].rdev->nr_pending); atomic_inc(&r10_bio->remaining); @@ -1699,7 +1700,7 @@ static int run(mddev_t *mddev) mddev->queue->max_sectors = (PAGE_SIZE>>9); disk->head_position = 0; - if (!rdev->faulty && rdev->in_sync) + if (!test_bit(Faulty, &rdev->flags) && test_bit(In_sync, &rdev->flags)) conf->working_disks++; } conf->raid_disks = mddev->raid_disks; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 77610b98d4e0..d1c488b008af 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -525,19 +525,19 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) raid5_conf_t *conf = (raid5_conf_t *) mddev->private; PRINTK("raid5: error called\n"); - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { mddev->sb_dirty = 1; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { conf->working_disks--; mddev->degraded++; conf->failed_disks++; - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); /* * if recovery was running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->faulty = 1; + set_bit(Faulty, &rdev->flags); printk (KERN_ALERT "raid5: Disk failure on %s, disabling device." " Operation continuing on %d devices\n", @@ -1003,12 +1003,12 @@ static void handle_stripe(struct stripe_head *sh) } if (dev->written) written++; rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ - if (!rdev || !rdev->in_sync) { + if (!rdev || !test_bit(In_sync, &rdev->flags)) { /* The ReadError flag wil just be confusing now */ clear_bit(R5_ReadError, &dev->flags); clear_bit(R5_ReWrite, &dev->flags); } - if (!rdev || !rdev->in_sync + if (!rdev || !test_bit(In_sync, &rdev->flags) || test_bit(R5_ReadError, &dev->flags)) { failed++; failed_num = i; @@ -1027,7 +1027,7 @@ static void handle_stripe(struct stripe_head *sh) if (test_bit(R5_ReadError, &sh->dev[i].flags)) { mdk_rdev_t *rdev = conf->disks[i].rdev; - if (rdev && rdev->in_sync) + if (rdev && test_bit(In_sync, &rdev->flags)) /* multiple read failures in one stripe */ md_error(conf->mddev, rdev); } @@ -1384,7 +1384,7 @@ static void handle_stripe(struct stripe_head *sh) rcu_read_lock(); rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && rdev->faulty) + if (rdev && test_bit(Faulty, &rdev->flags)) rdev = NULL; if (rdev) atomic_inc(&rdev->nr_pending); @@ -1458,7 +1458,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -1503,7 +1503,7 @@ static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -1850,7 +1850,7 @@ static int run(mddev_t *mddev) disk->rdev = rdev; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { char b[BDEVNAME_SIZE]; printk(KERN_INFO "raid5: device %s operational as raid" " disk %d\n", bdevname(rdev->bdev,b), @@ -2029,7 +2029,7 @@ static void status (struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf (seq, "%s", conf->disks[i].rdev && - conf->disks[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); #if RAID5_DEBUG #define D(x) \ @@ -2056,7 +2056,7 @@ static void print_raid5_conf (raid5_conf_t *conf) tmp = conf->disks + i; if (tmp->rdev) printk(" disk %d, o:%d, dev:%s\n", - i, !tmp->rdev->faulty, + i, !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -2070,12 +2070,12 @@ static int raid5_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { mddev->degraded--; conf->failed_disks--; conf->working_disks++; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } print_raid5_conf(conf); @@ -2092,7 +2092,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number) print_raid5_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -2127,7 +2127,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) */ for (disk=0; disk < mddev->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; found = 1; if (rdev->saved_raid_disk != disk) diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 84f3ee01e4c8..eae5a35629c5 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -507,19 +507,19 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) raid6_conf_t *conf = (raid6_conf_t *) mddev->private; PRINTK("raid6: error called\n"); - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { mddev->sb_dirty = 1; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { conf->working_disks--; mddev->degraded++; conf->failed_disks++; - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); /* * if recovery was running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->faulty = 1; + set_bit(Faulty, &rdev->flags); printk (KERN_ALERT "raid6: Disk failure on %s, disabling device." " Operation continuing on %d devices\n", @@ -1071,7 +1071,7 @@ static void handle_stripe(struct stripe_head *sh) } if (dev->written) written++; rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ - if (!rdev || !rdev->in_sync) { + if (!rdev || !test_bit(In_sync, &rdev->flags)) { if ( failed < 2 ) failed_num[failed] = i; failed++; @@ -1465,7 +1465,7 @@ static void handle_stripe(struct stripe_head *sh) rcu_read_lock(); rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && rdev->faulty) + if (rdev && test_bit(Faulty, &rdev->flags)) rdev = NULL; if (rdev) atomic_inc(&rdev->nr_pending); @@ -1539,7 +1539,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -1584,7 +1584,7 @@ static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -1868,7 +1868,7 @@ static int run(mddev_t *mddev) disk->rdev = rdev; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { char b[BDEVNAME_SIZE]; printk(KERN_INFO "raid6: device %s operational as raid" " disk %d\n", bdevname(rdev->bdev,b), @@ -2052,7 +2052,7 @@ static void status (struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf (seq, "%s", conf->disks[i].rdev && - conf->disks[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); #if RAID6_DUMPSTATE seq_printf (seq, "\n"); @@ -2078,7 +2078,7 @@ static void print_raid6_conf (raid6_conf_t *conf) tmp = conf->disks + i; if (tmp->rdev) printk(" disk %d, o:%d, dev:%s\n", - i, !tmp->rdev->faulty, + i, !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -2092,12 +2092,12 @@ static int raid6_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { mddev->degraded--; conf->failed_disks--; conf->working_disks++; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } print_raid6_conf(conf); @@ -2114,7 +2114,7 @@ static int raid6_remove_disk(mddev_t *mddev, int number) print_raid6_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -2149,7 +2149,7 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) */ for (disk=0; disk < mddev->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; found = 1; if (rdev->saved_raid_disk != disk) diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 200c69e34fc0..11629f92180a 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -117,10 +117,10 @@ struct mdk_rdev_s * It can never have faulty==1, in_sync==1 * This reduces the burden of testing multiple flags in many cases */ - int faulty; /* if faulty do not issue IO requests */ - int in_sync; /* device is a full member of the array */ - unsigned long flags; /* Should include faulty and in_sync here. */ + unsigned long flags; +#define Faulty 1 /* device is known to have a fault */ +#define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ int desc_nr; /* descriptor index in the superblock */ @@ -247,7 +247,7 @@ struct mddev_s static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev) { - int faulty = rdev->faulty; + int faulty = test_bit(Faulty, &rdev->flags); if (atomic_dec_and_test(&rdev->nr_pending) && faulty) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } -- cgit v1.2.3 From bd926c63b7a6843d3ce2728396c0891e54fce5c4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:32 -0800 Subject: [PATCH] md: make md on-disk bitmaps not host-endian Current bitmaps use set_bit et.al and so are host-endian, which means not-portable. Oops. Define a new version number (4) for which bitmaps are little-endian. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 22 ++++++++++++++++++---- drivers/md/md.c | 2 +- include/linux/raid/bitmap.h | 11 +++++++++-- include/linux/raid/md.h | 4 +++- 4 files changed, 31 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c5fa4c2a5af1..220273e81ed6 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -482,7 +482,8 @@ static int bitmap_read_sb(struct bitmap *bitmap) /* verify that the bitmap-specific fields are valid */ if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) reason = "bad magic"; - else if (sb->version != cpu_to_le32(BITMAP_MAJOR)) + else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || + le32_to_cpu(sb->version) > BITMAP_MAJOR_HI) reason = "unrecognized superblock version"; else if (chunksize < 512 || chunksize > (1024 * 1024 * 4)) reason = "bitmap chunksize out of range (512B - 4MB)"; @@ -527,6 +528,8 @@ success: bitmap->daemon_lastrun = jiffies; bitmap->max_write_behind = write_behind; bitmap->flags |= sb->state; + if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) + bitmap->flags |= BITMAP_HOSTENDIAN; bitmap->events_cleared = le64_to_cpu(sb->events_cleared); if (sb->state & BITMAP_STALE) bitmap->events_cleared = bitmap->mddev->events; @@ -764,7 +767,10 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) /* set the bit */ kaddr = kmap_atomic(page, KM_USER0); - set_bit(bit, kaddr); + if (bitmap->flags & BITMAP_HOSTENDIAN) + set_bit(bit, kaddr); + else + ext2_set_bit(bit, kaddr); kunmap_atomic(kaddr, KM_USER0); PRINTK("set file bit %lu page %lu\n", bit, page->index); @@ -891,6 +897,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) oldindex = ~0L; for (i = 0; i < chunks; i++) { + int b; index = file_page_index(i); bit = file_page_offset(i); if (index != oldindex) { /* this is a new page, read it in */ @@ -939,7 +946,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) bitmap->filemap[bitmap->file_pages++] = page; } - if (test_bit(bit, page_address(page))) { + if (bitmap->flags & BITMAP_HOSTENDIAN) + b = test_bit(bit, page_address(page)); + else + b = ext2_test_bit(bit, page_address(page)); + if (b) { /* if the disk bit is set, set the memory bit */ bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start) @@ -1097,7 +1108,10 @@ int bitmap_daemon_work(struct bitmap *bitmap) -1); /* clear the bit */ - clear_bit(file_page_offset(j), page_address(page)); + if (bitmap->flags & BITMAP_HOSTENDIAN) + clear_bit(file_page_offset(j), page_address(page)); + else + ext2_clear_bit(file_page_offset(j), page_address(page)); } } spin_unlock_irqrestore(&bitmap->lock, flags); diff --git a/drivers/md/md.c b/drivers/md/md.c index 9dfa063d1c6a..caa4add00c1b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4281,7 +4281,7 @@ static int __init md_init(void) " MD_SB_DISKS=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); - printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR, + printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR_HI, BITMAP_MINOR); if (register_blkdev(MAJOR_NR, "md")) diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 9de99198caf1..899437802aea 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h @@ -6,7 +6,13 @@ #ifndef BITMAP_H #define BITMAP_H 1 -#define BITMAP_MAJOR 3 +#define BITMAP_MAJOR_LO 3 +/* version 4 insists the bitmap is in little-endian order + * with version 3, it is host-endian which is non-portable + */ +#define BITMAP_MAJOR_HI 4 +#define BITMAP_MAJOR_HOSTENDIAN 3 + #define BITMAP_MINOR 39 /* @@ -133,7 +139,8 @@ typedef __u16 bitmap_counter_t; /* use these for bitmap->flags and bitmap->sb->state bit-fields */ enum bitmap_state { BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ - BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */ + BITMAP_STALE = 0x002, /* the bitmap file is out of date or had -EIO */ + BITMAP_HOSTENDIAN = 0x8000, }; /* the superblock at the front of the bitmap file -- little endian */ diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index ffa316ce4dc8..91467a3c4a52 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -66,8 +66,10 @@ * and major_version/minor_version accordingly * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT * in the super status byte + * >=3 means that bitmap superblock version 4 is supported, which uses + * little-ending representation rather than host-endian */ -#define MD_PATCHLEVEL_VERSION 2 +#define MD_PATCHLEVEL_VERSION 3 extern int register_md_personality (int p_num, mdk_personality_t *p); extern int unregister_md_personality (int p_num); -- cgit v1.2.3 From a9701a30470856408d08657eb1bd7ae29a146190 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:34 -0800 Subject: [PATCH] md: support BIO_RW_BARRIER for md/raid1 We can only accept BARRIER requests if all slaves handle barriers, and that can, of course, change with time.... So we keep track of whether the whole array seems safe for barriers, and also whether each individual rdev handles barriers. We initially assumes barriers are OK. When writing the superblock we try a barrier, and if that fails, we flag things for no-barriers. This will usually clear the flags fairly quickly. If writing the superblock finds that BIO_RW_BARRIER is -ENOTSUPP, we need to resubmit, so introduce function "md_super_wait" which waits for requests to finish, and retries ENOTSUPP requests without the barrier flag. When writing the real raid1, write requests which were BIO_RW_BARRIER but which aresn't supported need to be retried. So raid1d is enhanced to do this, and when any bio write completes (i.e. no retry needed) we remove it from the r1bio, so that devices needing retry are easy to find. We should hardly ever get -ENOTSUPP errors when writing data to the raid. It should only happen if: 1/ the device used to support BARRIER, but now doesn't. Few devices change like this, though raid1 can! or 2/ the array has no persistent superblock, so there was no opportunity to pre-test for barriers when writing the superblock. Signed-off-by: Neil Brown Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 5 +- drivers/md/md.c | 99 +++++++++++++++++++++++++++------ drivers/md/raid1.c | 134 +++++++++++++++++++++++++++++++-------------- include/linux/raid/md.h | 1 + include/linux/raid/md_k.h | 8 +++ include/linux/raid/raid1.h | 4 +- 6 files changed, 189 insertions(+), 62 deletions(-) (limited to 'include') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 220273e81ed6..51315302a85e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -301,7 +301,7 @@ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wai page); if (wait) - wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); + md_super_wait(mddev); return 0; } @@ -828,8 +828,7 @@ int bitmap_unplug(struct bitmap *bitmap) wake_up_process(bitmap->writeback_daemon->tsk)); spin_unlock_irq(&bitmap->write_lock); } else - wait_event(bitmap->mddev->sb_wait, - atomic_read(&bitmap->mddev->pending_writes)==0); + md_super_wait(bitmap->mddev); } return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index caa4add00c1b..199016932de5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -330,18 +330,46 @@ static void free_disk_sb(mdk_rdev_t * rdev) static int super_written(struct bio *bio, unsigned int bytes_done, int error) { mdk_rdev_t *rdev = bio->bi_private; + mddev_t *mddev = rdev->mddev; if (bio->bi_size) return 1; if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) - md_error(rdev->mddev, rdev); + md_error(mddev, rdev); - if (atomic_dec_and_test(&rdev->mddev->pending_writes)) - wake_up(&rdev->mddev->sb_wait); + if (atomic_dec_and_test(&mddev->pending_writes)) + wake_up(&mddev->sb_wait); bio_put(bio); return 0; } +static int super_written_barrier(struct bio *bio, unsigned int bytes_done, int error) +{ + struct bio *bio2 = bio->bi_private; + mdk_rdev_t *rdev = bio2->bi_private; + mddev_t *mddev = rdev->mddev; + if (bio->bi_size) + return 1; + + if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && + error == -EOPNOTSUPP) { + unsigned long flags; + /* barriers don't appear to be supported :-( */ + set_bit(BarriersNotsupp, &rdev->flags); + mddev->barriers_work = 0; + spin_lock_irqsave(&mddev->write_lock, flags); + bio2->bi_next = mddev->biolist; + mddev->biolist = bio2; + spin_unlock_irqrestore(&mddev->write_lock, flags); + wake_up(&mddev->sb_wait); + bio_put(bio); + return 0; + } + bio_put(bio2); + bio->bi_private = rdev; + return super_written(bio, bytes_done, error); +} + void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, sector_t sector, int size, struct page *page) { @@ -350,16 +378,54 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, * and decrement it on completion, waking up sb_wait * if zero is reached. * If an error occurred, call md_error + * + * As we might need to resubmit the request if BIO_RW_BARRIER + * causes ENOTSUPP, we allocate a spare bio... */ struct bio *bio = bio_alloc(GFP_NOIO, 1); + int rw = (1<bi_bdev = rdev->bdev; bio->bi_sector = sector; bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; + bio->bi_rw = rw; + atomic_inc(&mddev->pending_writes); - submit_bio((1<flags)) { + struct bio *rbio; + rw |= (1<bi_private = bio; + rbio->bi_end_io = super_written_barrier; + submit_bio(rw, rbio); + } else + submit_bio(rw, bio); +} + +void md_super_wait(mddev_t *mddev) +{ + /* wait for all superblock writes that were scheduled to complete. + * if any had to be retried (due to BARRIER problems), retry them + */ + DEFINE_WAIT(wq); + for(;;) { + prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE); + if (atomic_read(&mddev->pending_writes)==0) + break; + while (mddev->biolist) { + struct bio *bio; + spin_lock_irq(&mddev->write_lock); + bio = mddev->biolist; + mddev->biolist = bio->bi_next ; + bio->bi_next = NULL; + spin_unlock_irq(&mddev->write_lock); + submit_bio(bio->bi_rw, bio); + } + schedule(); + } + finish_wait(&mddev->sb_wait, &wq); } static int bi_complete(struct bio *bio, unsigned int bytes_done, int error) @@ -1382,7 +1448,7 @@ static void md_update_sb(mddev_t * mddev) int sync_req; repeat: - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); sync_req = mddev->in_sync; mddev->utime = get_seconds(); mddev->events ++; @@ -1405,11 +1471,11 @@ repeat: */ if (!mddev->persistent) { mddev->sb_dirty = 0; - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); wake_up(&mddev->sb_wait); return; } - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); dprintk(KERN_INFO "md: updating %s RAID superblock on device (in sync %d)\n", @@ -1437,17 +1503,17 @@ repeat: /* only need to write one superblock... */ break; } - wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); + md_super_wait(mddev); /* if there was a failure, sb_dirty was set to 1, and we re-write super */ - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); if (mddev->in_sync != sync_req|| mddev->sb_dirty == 1) { /* have to write it out again */ - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); goto repeat; } mddev->sb_dirty = 0; - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); wake_up(&mddev->sb_wait); } @@ -1989,6 +2055,7 @@ static int do_md_run(mddev_t * mddev) mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ + mddev->barriers_work = 1; /* before we start the array running, initialise the bitmap */ err = bitmap_create(mddev); @@ -2107,7 +2174,7 @@ static int do_md_stop(mddev_t * mddev, int ro) mddev->ro = 1; } else { bitmap_flush(mddev); - wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); + md_super_wait(mddev); if (mddev->ro) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); @@ -3796,13 +3863,13 @@ void md_write_start(mddev_t *mddev, struct bio *bi) atomic_inc(&mddev->writes_pending); if (mddev->in_sync) { - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); if (mddev->in_sync) { mddev->in_sync = 0; mddev->sb_dirty = 1; md_wakeup_thread(mddev->thread); } - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); } wait_event(mddev->sb_wait, mddev->sb_dirty==0); } @@ -4112,7 +4179,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev_trylock(mddev)==0) { int spares =0; - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; @@ -4120,7 +4187,7 @@ void md_check_recovery(mddev_t *mddev) } if (mddev->safemode == 1) mddev->safemode = 0; - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); if (mddev->sb_dirty) md_update_sb(mddev); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index fb6b866c28f5..1cbf51fbd43f 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -301,7 +301,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); - int mirror, behind; + int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state); conf_t *conf = mddev_to_conf(r1_bio->mddev); if (bio->bi_size) @@ -311,47 +311,54 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int if (r1_bio->bios[mirror] == bio) break; - /* - * this branch is our 'one mirror IO has finished' event handler: - */ - if (!uptodate) { - md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); - /* an I/O failed, we can't clear the bitmap */ - set_bit(R1BIO_Degraded, &r1_bio->state); - } else + if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) { + set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags); + set_bit(R1BIO_BarrierRetry, &r1_bio->state); + r1_bio->mddev->barriers_work = 0; + } else { /* - * Set R1BIO_Uptodate in our master bio, so that - * we will return a good error code for to the higher - * levels even if IO on some other mirrored buffer fails. - * - * The 'master' represents the composite IO operation to - * user-side. So if something waits for IO, then it will - * wait for the 'master' bio. + * this branch is our 'one mirror IO has finished' event handler: */ - set_bit(R1BIO_Uptodate, &r1_bio->state); - - update_head_pos(mirror, r1_bio); - - behind = test_bit(R1BIO_BehindIO, &r1_bio->state); - if (behind) { - if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags)) - atomic_dec(&r1_bio->behind_remaining); - - /* In behind mode, we ACK the master bio once the I/O has safely - * reached all non-writemostly disks. Setting the Returned bit - * ensures that this gets done only once -- we don't ever want to - * return -EIO here, instead we'll wait */ - - if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) && - test_bit(R1BIO_Uptodate, &r1_bio->state)) { - /* Maybe we can return now */ - if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) { - struct bio *mbio = r1_bio->master_bio; - PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n", - (unsigned long long) mbio->bi_sector, - (unsigned long long) mbio->bi_sector + - (mbio->bi_size >> 9) - 1); - bio_endio(mbio, mbio->bi_size, 0); + r1_bio->bios[mirror] = NULL; + bio_put(bio); + if (!uptodate) { + md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); + /* an I/O failed, we can't clear the bitmap */ + set_bit(R1BIO_Degraded, &r1_bio->state); + } else + /* + * Set R1BIO_Uptodate in our master bio, so that + * we will return a good error code for to the higher + * levels even if IO on some other mirrored buffer fails. + * + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. + */ + set_bit(R1BIO_Uptodate, &r1_bio->state); + + update_head_pos(mirror, r1_bio); + + if (behind) { + if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags)) + atomic_dec(&r1_bio->behind_remaining); + + /* In behind mode, we ACK the master bio once the I/O has safely + * reached all non-writemostly disks. Setting the Returned bit + * ensures that this gets done only once -- we don't ever want to + * return -EIO here, instead we'll wait */ + + if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) && + test_bit(R1BIO_Uptodate, &r1_bio->state)) { + /* Maybe we can return now */ + if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) { + struct bio *mbio = r1_bio->master_bio; + PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n", + (unsigned long long) mbio->bi_sector, + (unsigned long long) mbio->bi_sector + + (mbio->bi_size >> 9) - 1); + bio_endio(mbio, mbio->bi_size, 0); + } } } } @@ -361,8 +368,16 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int * already. */ if (atomic_dec_and_test(&r1_bio->remaining)) { + if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { + reschedule_retry(r1_bio); + /* Don't dec_pending yet, we want to hold + * the reference over the retry + */ + return 0; + } if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { /* free extra copy of the data pages */ +/* FIXME bio has been freed!!! */ int i = bio->bi_vcnt; while (i--) __free_page(bio->bi_io_vec[i].bv_page); @@ -648,8 +663,9 @@ static int make_request(request_queue_t *q, struct bio * bio) struct bio_list bl; struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); + int do_barriers; - if (unlikely(bio_barrier(bio))) { + if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { bio_endio(bio, bio->bi_size, -EOPNOTSUPP); return 0; } @@ -759,6 +775,10 @@ static int make_request(request_queue_t *q, struct bio * bio) atomic_set(&r1_bio->remaining, 0); atomic_set(&r1_bio->behind_remaining, 0); + do_barriers = bio->bi_rw & BIO_RW_BARRIER; + if (do_barriers) + set_bit(R1BIO_Barrier, &r1_bio->state); + bio_list_init(&bl); for (i = 0; i < disks; i++) { struct bio *mbio; @@ -771,7 +791,7 @@ static int make_request(request_queue_t *q, struct bio * bio) mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; - mbio->bi_rw = WRITE; + mbio->bi_rw = WRITE | do_barriers; mbio->bi_private = r1_bio; if (behind_pages) { @@ -1153,6 +1173,36 @@ static void raid1d(mddev_t *mddev) if (test_bit(R1BIO_IsSync, &r1_bio->state)) { sync_request_write(mddev, r1_bio); unplug = 1; + } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { + /* some requests in the r1bio were BIO_RW_BARRIER + * requests which failed with -ENOTSUPP. Hohumm.. + * Better resubmit without the barrier. + * We know which devices to resubmit for, because + * all others have had their bios[] entry cleared. + */ + int i; + clear_bit(R1BIO_BarrierRetry, &r1_bio->state); + clear_bit(R1BIO_Barrier, &r1_bio->state); + for (i=0; i < conf->raid_disks; i++) + if (r1_bio->bios[i]) { + struct bio_vec *bvec; + int j; + + bio = bio_clone(r1_bio->master_bio, GFP_NOIO); + /* copy pages from the failed bio, as + * this might be a write-behind device */ + __bio_for_each_segment(bvec, bio, j, 0) + bvec->bv_page = bio_iovec_idx(r1_bio->bios[i], j)->bv_page; + bio_put(r1_bio->bios[i]); + bio->bi_sector = r1_bio->sector + + conf->mirrors[i].rdev->data_offset; + bio->bi_bdev = conf->mirrors[i].rdev->bdev; + bio->bi_end_io = raid1_end_write_request; + bio->bi_rw = WRITE; + bio->bi_private = r1_bio; + r1_bio->bios[i] = bio; + generic_make_request(bio); + } } else { int disk; bio = r1_bio->bios[r1_bio->read_disk]; diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 91467a3c4a52..13e7c4b62367 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -89,6 +89,7 @@ extern void md_print_devices (void); extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, sector_t sector, int size, struct page *page); +extern void md_super_wait(mddev_t *mddev); extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, struct page *page, int rw); diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 11629f92180a..d5854c2b2721 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -122,6 +122,7 @@ struct mdk_rdev_s #define Faulty 1 /* device is known to have a fault */ #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ +#define BarriersNotsupp 5 /* BIO_RW_BARRIER is not supported */ int desc_nr; /* descriptor index in the superblock */ int raid_disk; /* role of device in array */ @@ -210,6 +211,13 @@ struct mddev_s int degraded; /* whether md should consider * adding a spare */ + int barriers_work; /* initialised to true, cleared as soon + * as a barrier request to slave + * fails. Only supported + */ + struct bio *biolist; /* bios that need to be retried + * because BIO_RW_BARRIER is not supported + */ atomic_t recovery_active; /* blocks scheduled, but not written */ wait_queue_head_t recovery_wait; diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index 60e19b667548..292b98f2b408 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h @@ -110,7 +110,9 @@ struct r1bio_s { #define R1BIO_Uptodate 0 #define R1BIO_IsSync 1 #define R1BIO_Degraded 2 -#define R1BIO_BehindIO 3 +#define R1BIO_BehindIO 3 +#define R1BIO_Barrier 4 +#define R1BIO_BarrierRetry 5 /* For write-behind requests, we call bi_end_io when * the last non-write-behind device completes, providing * any write was successful. Otherwise we call when -- cgit v1.2.3 From 787453c2397edcc3261efebb661739acd8c38547 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:43 -0800 Subject: [PATCH] md: complete conversion of md to use kthreads There are a few loose ends following the conversion of md to use kthreads: - Some fields in mdk_thread_t that aren't needed (kthreads does it's own completion and manages it's own name). - thread->run is now never NULL, so no need to check - Some tests for signal_pending that aren't needed (As we don't use signals to stop threads any more) - Some flush_signals are not needed - Some waits are interruptible and don't need to be. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 33 ++++++++++----------------------- include/linux/raid/md_k.h | 2 -- 2 files changed, 10 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/md/md.c b/drivers/md/md.c index 25f2bbfe6a2b..097ae1b5484b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3424,21 +3424,17 @@ static int md_thread(void * arg) */ allow_signal(SIGKILL); - complete(thread->event); while (!kthread_should_stop()) { - void (*run)(mddev_t *); - wait_event_interruptible_timeout(thread->wqueue, - test_bit(THREAD_WAKEUP, &thread->flags) - || kthread_should_stop(), - thread->timeout); + wait_event_timeout(thread->wqueue, + test_bit(THREAD_WAKEUP, &thread->flags) + || kthread_should_stop(), + thread->timeout); try_to_freeze(); clear_bit(THREAD_WAKEUP, &thread->flags); - run = thread->run; - if (run) - run(thread->mddev); + thread->run(thread->mddev); } return 0; @@ -3457,7 +3453,6 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, const char *name) { mdk_thread_t *thread; - struct completion event; thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL); if (!thread) @@ -3466,18 +3461,14 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, memset(thread, 0, sizeof(mdk_thread_t)); init_waitqueue_head(&thread->wqueue); - init_completion(&event); - thread->event = &event; thread->run = run; thread->mddev = mddev; - thread->name = name; thread->timeout = MAX_SCHEDULE_TIMEOUT; thread->tsk = kthread_run(md_thread, thread, name, mdname(thread->mddev)); if (IS_ERR(thread->tsk)) { kfree(thread); return NULL; } - wait_for_completion(&event); return thread; } @@ -3941,9 +3932,7 @@ static void md_do_sync(mddev_t *mddev) mddev->curr_resync = 2; try_again: - if (signal_pending(current) || - kthread_should_stop()) { - flush_signals(current); + if (kthread_should_stop()) { set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto skip; } @@ -3963,9 +3952,8 @@ static void md_do_sync(mddev_t *mddev) * time 'round when curr_resync == 2 */ continue; - prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); - if (!signal_pending(current) && - !kthread_should_stop() && + prepare_to_wait(&resync_wait, &wq, TASK_UNINTERRUPTIBLE); + if (!kthread_should_stop() && mddev2->curr_resync >= mddev->curr_resync) { printk(KERN_INFO "md: delaying resync of %s" " until %s has finished resync (they" @@ -4074,13 +4062,12 @@ static void md_do_sync(mddev_t *mddev) } - if (signal_pending(current) || kthread_should_stop()) { + if (kthread_should_stop()) { /* * got a signal, exit. */ printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n"); - flush_signals(current); set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto out; } @@ -4102,7 +4089,7 @@ static void md_do_sync(mddev_t *mddev) if (currspeed > sysctl_speed_limit_min) { if ((currspeed > sysctl_speed_limit_max) || !is_mddev_idle(mddev)) { - msleep_interruptible(250); + msleep(250); goto repeat; } } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index d5854c2b2721..46629a275ba9 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -334,10 +334,8 @@ typedef struct mdk_thread_s { mddev_t *mddev; wait_queue_head_t wqueue; unsigned long flags; - struct completion *event; struct task_struct *tsk; unsigned long timeout; - const char *name; } mdk_thread_t; #define THREAD_WAKEUP 0 -- cgit v1.2.3 From a2506c04322ca266fe2f9bd7d02a67b1972da611 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 9 Nov 2005 12:59:13 -0800 Subject: [NETFILTER] nfnetlink: nfattr_parse() can never fail, make it void nfattr_parse (and thus nfattr_parse_nested) always returns success. So we can make them 'void' and remove all the checking at the caller side. Based on original patch by Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink.h | 2 +- net/ipv4/netfilter/ip_conntrack_netlink.c | 45 +++++------------------------ net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 6 +--- net/netfilter/nfnetlink.c | 4 +-- 4 files changed, 11 insertions(+), 46 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index f08e870100f4..72975fa8795d 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -146,7 +146,7 @@ extern void nfnl_unlock(void); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); -extern int nfattr_parse(struct nfattr *tb[], int maxattr, +extern void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len); #define nfattr_parse_nested(tb, max, nfa) \ diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 02f303cf201e..838262e17376 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -482,9 +482,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("entered %s\n", __FUNCTION__); - - if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_IP_MAX, attr); if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; @@ -500,9 +498,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } static const int cta_min_proto[CTA_PROTO_MAX] = { @@ -524,8 +519,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) return -EINVAL; @@ -542,9 +536,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, } return ret; - -nfattr_failure: - return -1; } static inline int @@ -558,8 +549,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, memset(tuple, 0, sizeof(*tuple)); - if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); if (!tb[CTA_TUPLE_IP-1]) return -EINVAL; @@ -586,9 +576,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } #ifdef CONFIG_IP_NF_NAT_NEEDED @@ -606,11 +593,10 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) - goto nfattr_failure; + return -1; npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); if (!npt) @@ -629,9 +615,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } static inline int @@ -645,8 +628,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], memset(range, 0, sizeof(*range)); - if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); if (tb[CTA_NAT_MINIP-1]) range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); @@ -668,9 +650,6 @@ ctnetlink_parse_nat(struct nfattr *cda[], DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } #endif @@ -681,8 +660,7 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_HELP_MAX, attr); if (!tb[CTA_HELP_NAME-1]) return -EINVAL; @@ -690,9 +668,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); return 0; - -nfattr_failure: - return -1; } static int @@ -960,8 +935,7 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; int err = 0; - if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); proto = ip_conntrack_proto_find_get(npt); if (!proto) @@ -972,9 +946,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) ip_conntrack_proto_put(proto); return err; - -nfattr_failure: - return -ENOMEM; } static int diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index d6701cafbcc2..6ea4b22ff28d 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -362,8 +362,7 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; - if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); if (!tb[CTA_PROTOINFO_TCP_STATE-1]) return -EINVAL; @@ -374,9 +373,6 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) write_unlock_bh(&tcp_lock); return 0; - -nfattr_failure: - return -1; } #endif diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 4bc27a6334c1..f8bd7c7e7921 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -128,7 +128,7 @@ void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen, memset(NFA_DATA(nfa) + attrlen, 0, NFA_ALIGN(size) - size); } -int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) +void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) { memset(tb, 0, sizeof(struct nfattr *) * maxattr); @@ -138,8 +138,6 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) tb[flavor-1] = nfa; nfa = NFA_NEXT(nfa, len); } - - return 0; } /** -- cgit v1.2.3