Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
179b6179
Commit
179b6179
authored
Feb 17, 2003
by
Alan Cox
Committed by
Linus Torvalds
Feb 17, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] update ide.c
Remove ide_ioreg_t Add locking on the ide setting lists
parent
15e51b0a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
128 additions
and
55 deletions
+128
-55
drivers/ide/ide.c
drivers/ide/ide.c
+128
-55
No files found.
drivers/ide/ide.c
View file @
179b6179
...
...
@@ -833,8 +833,8 @@ EXPORT_SYMBOL(ide_unregister);
*/
void
ide_setup_ports
(
hw_regs_t
*
hw
,
ide_ioreg_t
base
,
int
*
offsets
,
ide_ioreg_t
ctrl
,
ide_ioreg_t
intr
,
unsigned
long
base
,
int
*
offsets
,
unsigned
long
ctrl
,
unsigned
long
intr
,
ide_ack_intr_t
*
ack_intr
,
/*
* ide_io_ops_t *iops,
...
...
@@ -930,38 +930,52 @@ EXPORT_SYMBOL(ide_register_hw);
int
ide_register
(
int
arg1
,
int
arg2
,
int
irq
)
{
hw_regs_t
hw
;
ide_init_hwif_ports
(
&
hw
,
(
ide_ioreg_t
)
arg1
,
(
ide_ioreg_t
)
arg2
,
NULL
);
ide_init_hwif_ports
(
&
hw
,
(
unsigned
long
)
arg1
,
(
unsigned
long
)
arg2
,
NULL
);
hw
.
irq
=
irq
;
return
ide_register_hw
(
&
hw
,
NULL
);
}
EXPORT_SYMBOL
(
ide_register
);
/*
* Locks for IDE setting functionality
*/
DECLARE_MUTEX
(
ide_setting_sem
);
EXPORT_SYMBOL
(
ide_setting_sem
);
/**
* ide_add_setting
- attach an IDE setting
*
drive: drive the setting is for
*
name: name of setting
*
rw: set if writabl
e
*
read_ioctl: read function
*
write_ioctl: write function
*
data_type: form expected
*
min:
minimum
*
max:
maximum
*
mul_factor: multiply by
*
div_factor: divide by
*
data: value
*
set: handling for
setting
* ide_add_setting
- add an ide setting option
*
@drive: drive to use
*
@name: setting name
*
@rw: true if the function is read writ
e
*
@read_ioctl: function to call on read
*
@write_ioctl: function to call on write
*
@data_type: type of data
*
@min: range
minimum
*
@max: range
maximum
*
@mul_factor: multiplication scale
*
@div_factor: divison scale
*
@data: private data field
*
@set:
setting
*
* Add a setting to the IDE drive. Support automatic removal and allow
* all the work to be done by plugged in handlers. This code is also
* rather short on locking, but the current plan is to do the locking
* internally to the function.
* Removes the setting named from the device if it is present.
* The function takes the settings_lock to protect against
* parallel changes. This function must not be called from IRQ
* context. Returns 0 on success or -1 on failure.
*
* BUGS: This code is seriously over-engineered. There is also
* magic about how the driver specific features are setup. If
* a driver is attached we assume the driver settings are auto
* remove.
*/
void
ide_add_setting
(
ide_drive_t
*
drive
,
const
char
*
name
,
int
rw
,
int
read_ioctl
,
int
write_ioctl
,
int
data_type
,
int
min
,
int
max
,
int
mul_factor
,
int
div_factor
,
void
*
data
,
ide_procset_t
*
set
)
int
ide_add_setting
(
ide_drive_t
*
drive
,
const
char
*
name
,
int
rw
,
int
read_ioctl
,
int
write_ioctl
,
int
data_type
,
int
min
,
int
max
,
int
mul_factor
,
int
div_factor
,
void
*
data
,
ide_procset_t
*
set
)
{
ide_settings_t
**
p
=
(
ide_settings_t
**
)
&
drive
->
settings
,
*
setting
=
NULL
;
down
(
&
ide_setting_sem
);
while
((
*
p
)
&&
strcmp
((
*
p
)
->
name
,
name
)
<
0
)
p
=
&
((
*
p
)
->
next
);
if
((
setting
=
kmalloc
(
sizeof
(
*
setting
),
GFP_KERNEL
))
==
NULL
)
...
...
@@ -980,49 +994,76 @@ void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioc
setting
->
div_factor
=
div_factor
;
setting
->
data
=
data
;
setting
->
set
=
set
;
setting
->
next
=
*
p
;
if
(
drive
->
driver
)
setting
->
auto_remove
=
1
;
*
p
=
setting
;
return
;
up
(
&
ide_setting_sem
);
return
0
;
abort:
up
(
&
ide_setting_sem
);
if
(
setting
)
kfree
(
setting
);
return
-
1
;
}
EXPORT_SYMBOL
(
ide_add_setting
);
/**
* ide_remove_setting - remove an ioctl setting
* @name: name of the property
* __ide_remove_setting - remove an ide setting option
* @drive: drive to use
* @name: setting name
*
* Remove
a drive ioctl setting that was created by ide_add_setting
.
*
Again this needs the locking fixed
* Remove
s the setting named from the device if it is present
.
*
The caller must hold the setting semaphore.
*/
void
ide_remove_setting
(
ide_drive_t
*
drive
,
char
*
name
)
static
void
__
ide_remove_setting
(
ide_drive_t
*
drive
,
char
*
name
)
{
ide_settings_t
**
p
=
(
ide_settings_t
**
)
&
drive
->
settings
,
*
setting
;
ide_settings_t
**
p
,
*
setting
;
p
=
(
ide_settings_t
**
)
&
drive
->
settings
;
while
((
*
p
)
&&
strcmp
((
*
p
)
->
name
,
name
))
p
=
&
((
*
p
)
->
next
);
if
((
setting
=
(
*
p
))
==
NULL
)
return
;
(
*
p
)
=
setting
->
next
;
kfree
(
setting
->
name
);
kfree
(
setting
);
}
/**
* ide_remove_setting - remove an ide setting option
* @drive: drive to use
* @name: setting name
*
* Removes the setting named from the device if it is present.
* The function takes the settings_lock to protect against
* parallel changes. This function must not be called from IRQ
* context.
*/
void
ide_remove_setting
(
ide_drive_t
*
drive
,
char
*
name
)
{
down
(
&
ide_setting_sem
);
__ide_remove_setting
(
drive
,
name
);
up
(
&
ide_setting_sem
);
}
EXPORT_SYMBOL
(
ide_remove_setting
);
/**
* ide_find_setting_by_ioctl - find a
setting handler by its command
* @drive: drive to
act for
* @cmd: ioctl command
cod
e
* ide_find_setting_by_ioctl - find a
drive specific ioctl
* @drive: drive to
scan
* @cmd: ioctl command
to handl
e
*
* Scan
the drive handlers for an ioctl handler for this function.
*
The handlers vary by drive and sometimes by drive state.
*
Needs locking fixes.
* Scan
's the device setting table for a matching entry and returns
*
this or NULL if no entry is found. The caller must hold the
*
setting semaphore
*/
static
ide_settings_t
*
ide_find_setting_by_ioctl
(
ide_drive_t
*
drive
,
int
cmd
)
...
...
@@ -1034,17 +1075,18 @@ static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd)
break
;
setting
=
setting
->
next
;
}
return
setting
;
}
/**
* ide_find_setting_by_name - find a
setting handler by its name
* @drive: drive to
act for
* @
cmd: ioctl command cod
e
* ide_find_setting_by_name - find a
drive specific setting
* @drive: drive to
scan
* @
name: setting nam
e
*
* Scan
the drive handlers handler matching the name for this function.
*
The handlers vary by drive and sometimes by drive state.
*
Needs locking fixes.
* Scan
's the device setting table for a matching entry and returns
*
this or NULL if no entry is found. The caller must hold the
*
setting semaphore
*/
ide_settings_t
*
ide_find_setting_by_name
(
ide_drive_t
*
drive
,
char
*
name
)
...
...
@@ -1060,30 +1102,43 @@ ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
}
/**
* auto_remove_settings - remove driver s
ettings on a device
* @drive: drive
to clean
* auto_remove_settings - remove driver s
pecific settings
* @drive: drive
*
* Called when we change the driver bindings for a device, for
* example if the device is hot plugged. We must scrub the driver
* bindings that are thus no longer relevant to the device in case
* it changes from say a CD-ROM to a disk
* Needs locking fixes
* Automatically remove all the driver specific settings for this
* drive. This function may sleep and must not be called from IRQ
* context. Takes the settings_lock
*/
static
void
auto_remove_settings
(
ide_drive_t
*
drive
)
{
ide_settings_t
*
setting
;
down
(
&
ide_setting_sem
);
repeat:
setting
=
drive
->
settings
;
while
(
setting
)
{
if
(
setting
->
auto_remove
)
{
ide_remove_setting
(
drive
,
setting
->
name
);
__
ide_remove_setting
(
drive
,
setting
->
name
);
goto
repeat
;
}
setting
=
setting
->
next
;
}
up
(
&
ide_setting_sem
);
}
/**
* ide_read_setting - read an IDE setting
* @drive: drive to read from
* @setting: drive setting
*
* Read a drive setting and return the value. The caller
* must hold the ide_setting_sem when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
* be told apart
*/
int
ide_read_setting
(
ide_drive_t
*
drive
,
ide_settings_t
*
setting
)
{
int
val
=
-
EINVAL
;
...
...
@@ -1132,10 +1187,22 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive)
EXPORT_SYMBOL
(
ide_spin_wait_hwgroup
);
/*
* FIXME: This should be changed to enqueue a special request
* to the driver to change settings, and then wait on a sema for completion.
* The current scheme of polling is kludgey, though safe enough.
/**
* ide_write_setting - read an IDE setting
* @drive: drive to read from
* @setting: drive setting
* @val: value
*
* Write a drive setting if it is possible. The caller
* must hold the ide_setting_sem when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
* be told apart
*
* FIXME: This should be changed to enqueue a special request
* to the driver to change settings, and then wait on a sema for completion.
* The current scheme of polling is kludgy, though safe enough.
*/
int
ide_write_setting
(
ide_drive_t
*
drive
,
ide_settings_t
*
setting
,
int
val
)
{
...
...
@@ -1360,16 +1427,22 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
ide_settings_t
*
setting
;
int
err
=
0
;
down
(
&
ide_setting_sem
);
if
((
setting
=
ide_find_setting_by_ioctl
(
drive
,
cmd
))
!=
NULL
)
{
if
(
cmd
==
setting
->
read_ioctl
)
{
err
=
ide_read_setting
(
drive
,
setting
);
up
(
&
ide_setting_sem
);
return
err
>=
0
?
put_user
(
err
,
(
long
*
)
arg
)
:
err
;
}
else
{
if
(
bdev
!=
bdev
->
bd_contains
)
return
-
EINVAL
;
return
ide_write_setting
(
drive
,
setting
,
arg
);
err
=
-
EINVAL
;
else
err
=
ide_write_setting
(
drive
,
setting
,
arg
);
up
(
&
ide_setting_sem
);
return
err
;
}
}
up
(
&
ide_setting_sem
);
switch
(
cmd
)
{
case
HDIO_GETGEO
:
...
...
@@ -1976,7 +2049,7 @@ int __init ide_setup (char *s)
vals
[
2
]
=
0
;
/* default irq = probe for it */
case
3
:
/* base,ctl,irq */
hwif
->
hw
.
irq
=
vals
[
2
];
ide_init_hwif_ports
(
&
hwif
->
hw
,
(
ide_ioreg_t
)
vals
[
0
],
(
ide_ioreg_t
)
vals
[
1
],
&
hwif
->
irq
);
ide_init_hwif_ports
(
&
hwif
->
hw
,
(
unsigned
long
)
vals
[
0
],
(
unsigned
long
)
vals
[
1
],
&
hwif
->
irq
);
memcpy
(
hwif
->
io_ports
,
hwif
->
hw
.
io_ports
,
sizeof
(
hwif
->
io_ports
));
hwif
->
irq
=
vals
[
2
];
hwif
->
noprobe
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment