diff --git a/[refs] b/[refs]
index 437de543061f..78bcaee25103 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: 9be16a03928642f944915b8c05945fd87b7a15cb
+refs/heads/master: 7fca0aa489c82bef85514b5447f6a0be81543115
diff --git a/trunk/Documentation/DocBook/libata.tmpl b/trunk/Documentation/DocBook/libata.tmpl
index d260d92089ad..375ae760dc1e 100644
--- a/trunk/Documentation/DocBook/libata.tmpl
+++ b/trunk/Documentation/DocBook/libata.tmpl
@@ -415,362 +415,6 @@ and other resources, etc.
-
- Error handling
-
-
- This chapter describes how errors are handled under libata.
- Readers are advised to read SCSI EH
- (Documentation/scsi/scsi_eh.txt) and ATA exceptions doc first.
-
-
- Origins of commands
-
- In libata, a command is represented with struct ata_queued_cmd
- or qc. qc's are preallocated during port initialization and
- repetitively used for command executions. Currently only one
- qc is allocated per port but yet-to-be-merged NCQ branch
- allocates one for each tag and maps each qc to NCQ tag 1-to-1.
-
-
- libata commands can originate from two sources - libata itself
- and SCSI midlayer. libata internal commands are used for
- initialization and error handling. All normal blk requests
- and commands for SCSI emulation are passed as SCSI commands
- through queuecommand callback of SCSI host template.
-
-
-
- How commands are issued
-
-
-
- Internal commands
-
-
- First, qc is allocated and initialized using
- ata_qc_new_init(). Although ata_qc_new_init() doesn't
- implement any wait or retry mechanism when qc is not
- available, internal commands are currently issued only during
- initialization and error recovery, so no other command is
- active and allocation is guaranteed to succeed.
-
-
- Once allocated qc's taskfile is initialized for the command to
- be executed. qc currently has two mechanisms to notify
- completion. One is via qc->complete_fn() callback and the
- other is completion qc->waiting. qc->complete_fn() callback
- is the asynchronous path used by normal SCSI translated
- commands and qc->waiting is the synchronous (issuer sleeps in
- process context) path used by internal commands.
-
-
- Once initialization is complete, host_set lock is acquired
- and the qc is issued.
-
-
-
-
- SCSI commands
-
-
- All libata drivers use ata_scsi_queuecmd() as
- hostt->queuecommand callback. scmds can either be simulated
- or translated. No qc is involved in processing a simulated
- scmd. The result is computed right away and the scmd is
- completed.
-
-
- For a translated scmd, ata_qc_new_init() is invoked to
- allocate a qc and the scmd is translated into the qc. SCSI
- midlayer's completion notification function pointer is stored
- into qc->scsidone.
-
-
- qc->complete_fn() callback is used for completion
- notification. ATA commands use ata_scsi_qc_complete() while
- ATAPI commands use atapi_qc_complete(). Both functions end up
- calling qc->scsidone to notify upper layer when the qc is
- finished. After translation is completed, the qc is issued
- with ata_qc_issue().
-
-
- Note that SCSI midlayer invokes hostt->queuecommand while
- holding host_set lock, so all above occur while holding
- host_set lock.
-
-
-
-
-
-
-
- How commands are processed
-
- Depending on which protocol and which controller are used,
- commands are processed differently. For the purpose of
- discussion, a controller which uses taskfile interface and all
- standard callbacks is assumed.
-
-
- Currently 6 ATA command protocols are used. They can be
- sorted into the following four categories according to how
- they are processed.
-
-
-
- ATA NO DATA or DMA
-
-
- ATA_PROT_NODATA and ATA_PROT_DMA fall into this category.
- These types of commands don't require any software
- intervention once issued. Device will raise interrupt on
- completion.
-
-
-
-
- ATA PIO
-
-
- ATA_PROT_PIO is in this category. libata currently
- implements PIO with polling. ATA_NIEN bit is set to turn
- off interrupt and pio_task on ata_wq performs polling and
- IO.
-
-
-
-
- ATAPI NODATA or DMA
-
-
- ATA_PROT_ATAPI_NODATA and ATA_PROT_ATAPI_DMA are in this
- category. packet_task is used to poll BSY bit after
- issuing PACKET command. Once BSY is turned off by the
- device, packet_task transfers CDB and hands off processing
- to interrupt handler.
-
-
-
-
- ATAPI PIO
-
-
- ATA_PROT_ATAPI is in this category. ATA_NIEN bit is set
- and, as in ATAPI NODATA or DMA, packet_task submits cdb.
- However, after submitting cdb, further processing (data
- transfer) is handed off to pio_task.
-
-
-
-
-
-
- How commands are completed
-
- Once issued, all qc's are either completed with
- ata_qc_complete() or time out. For commands which are handled
- by interrupts, ata_host_intr() invokes ata_qc_complete(), and,
- for PIO tasks, pio_task invokes ata_qc_complete(). In error
- cases, packet_task may also complete commands.
-
-
- ata_qc_complete() does the following.
-
-
-
-
-
-
- DMA memory is unmapped.
-
-
-
-
-
- ATA_QCFLAG_ACTIVE is clared from qc->flags.
-
-
-
-
-
- qc->complete_fn() callback is invoked. If the return value of
- the callback is not zero. Completion is short circuited and
- ata_qc_complete() returns.
-
-
-
-
-
- __ata_qc_complete() is called, which does
-
-
-
-
- qc->flags is cleared to zero.
-
-
-
-
-
- ap->active_tag and qc->tag are poisoned.
-
-
-
-
-
- qc->waiting is claread & completed (in that order).
-
-
-
-
-
- qc is deallocated by clearing appropriate bit in ap->qactive.
-
-
-
-
-
-
-
-
-
-
- So, it basically notifies upper layer and deallocates qc. One
- exception is short-circuit path in #3 which is used by
- atapi_qc_complete().
-
-
- For all non-ATAPI commands, whether it fails or not, almost
- the same code path is taken and very little error handling
- takes place. A qc is completed with success status if it
- succeeded, with failed status otherwise.
-
-
- However, failed ATAPI commands require more handling as
- REQUEST SENSE is needed to acquire sense data. If an ATAPI
- command fails, ata_qc_complete() is invoked with error status,
- which in turn invokes atapi_qc_complete() via
- qc->complete_fn() callback.
-
-
- This makes atapi_qc_complete() set scmd->result to
- SAM_STAT_CHECK_CONDITION, complete the scmd and return 1. As
- the sense data is empty but scmd->result is CHECK CONDITION,
- SCSI midlayer will invoke EH for the scmd, and returning 1
- makes ata_qc_complete() to return without deallocating the qc.
- This leads us to ata_scsi_error() with partially completed qc.
-
-
-
-
- ata_scsi_error()
-
- ata_scsi_error() is the current hostt->eh_strategy_handler()
- for libata. As discussed above, this will be entered in two
- cases - timeout and ATAPI error completion. This function
- calls low level libata driver's eng_timeout() callback, the
- standard callback for which is ata_eng_timeout(). It checks
- if a qc is active and calls ata_qc_timeout() on the qc if so.
- Actual error handling occurs in ata_qc_timeout().
-
-
- If EH is invoked for timeout, ata_qc_timeout() stops BMDMA and
- completes the qc. Note that as we're currently in EH, we
- cannot call scsi_done. As described in SCSI EH doc, a
- recovered scmd should be either retried with
- scsi_queue_insert() or finished with scsi_finish_command().
- Here, we override qc->scsidone with scsi_finish_command() and
- calls ata_qc_complete().
-
-
- If EH is invoked due to a failed ATAPI qc, the qc here is
- completed but not deallocated. The purpose of this
- half-completion is to use the qc as place holder to make EH
- code reach this place. This is a bit hackish, but it works.
-
-
- Once control reaches here, the qc is deallocated by invoking
- __ata_qc_complete() explicitly. Then, internal qc for REQUEST
- SENSE is issued. Once sense data is acquired, scmd is
- finished by directly invoking scsi_finish_command() on the
- scmd. Note that as we already have completed and deallocated
- the qc which was associated with the scmd, we don't need
- to/cannot call ata_qc_complete() again.
-
-
-
-
- Problems with the current EH
-
-
-
-
-
- Error representation is too crude. Currently any and all
- error conditions are represented with ATA STATUS and ERROR
- registers. Errors which aren't ATA device errors are treated
- as ATA device errors by setting ATA_ERR bit. Better error
- descriptor which can properly represent ATA and other
- errors/exceptions is needed.
-
-
-
-
-
- When handling timeouts, no action is taken to make device
- forget about the timed out command and ready for new commands.
-
-
-
-
-
- EH handling via ata_scsi_error() is not properly protected
- from usual command processing. On EH entrance, the device is
- not in quiescent state. Timed out commands may succeed or
- fail any time. pio_task and atapi_task may still be running.
-
-
-
-
-
- Too weak error recovery. Devices / controllers causing HSM
- mismatch errors and other errors quite often require reset to
- return to known state. Also, advanced error handling is
- necessary to support features like NCQ and hotplug.
-
-
-
-
-
- ATA errors are directly handled in the interrupt handler and
- PIO errors in pio_task. This is problematic for advanced
- error handling for the following reasons.
-
-
- First, advanced error handling often requires context and
- internal qc execution.
-
-
- Second, even a simple failure (say, CRC error) needs
- information gathering and could trigger complex error handling
- (say, resetting & reconfiguring). Having multiple code
- paths to gather information, enter EH and trigger actions
- makes life painful.
-
-
- Third, scattered EH code makes implementing low level drivers
- difficult. Low level drivers override libata callbacks. If
- EH is scattered over several places, each affected callbacks
- should perform its part of error handling. This can be error
- prone and painful.
-
-
-
-
-
-
-
libata Library
!Edrivers/scsi/libata-core.c
@@ -787,722 +431,6 @@ and other resources, etc.
!Idrivers/scsi/libata-scsi.c
-
- ATA errors & exceptions
-
-
- This chapter tries to identify what error/exception conditions exist
- for ATA/ATAPI devices and describe how they should be handled in
- implementation-neutral way.
-
-
-
- The term 'error' is used to describe conditions where either an
- explicit error condition is reported from device or a command has
- timed out.
-
-
-
- The term 'exception' is either used to describe exceptional
- conditions which are not errors (say, power or hotplug events), or
- to describe both errors and non-error exceptional conditions. Where
- explicit distinction between error and exception is necessary, the
- term 'non-error exception' is used.
-
-
-
- Exception categories
-
- Exceptions are described primarily with respect to legacy
- taskfile + bus master IDE interface. If a controller provides
- other better mechanism for error reporting, mapping those into
- categories described below shouldn't be difficult.
-
-
-
- In the following sections, two recovery actions - reset and
- reconfiguring transport - are mentioned. These are described
- further in .
-
-
-
- HSM violation
-
- This error is indicated when STATUS value doesn't match HSM
- requirement during issuing or excution any ATA/ATAPI command.
-
-
-
- Examples
-
-
-
- ATA_STATUS doesn't contain !BSY && DRDY && !DRQ while trying
- to issue a command.
-
-
-
-
-
- !BSY && !DRQ during PIO data transfer.
-
-
-
-
-
- DRQ on command completion.
-
-
-
-
-
- !BSY && ERR after CDB tranfer starts but before the
- last byte of CDB is transferred. ATA/ATAPI standard states
- that "The device shall not terminate the PACKET command
- with an error before the last byte of the command packet has
- been written" in the error outputs description of PACKET
- command and the state diagram doesn't include such
- transitions.
-
-
-
-
-
-
- In these cases, HSM is violated and not much information
- regarding the error can be acquired from STATUS or ERROR
- register. IOW, this error can be anything - driver bug,
- faulty device, controller and/or cable.
-
-
-
- As HSM is violated, reset is necessary to restore known state.
- Reconfiguring transport for lower speed might be helpful too
- as transmission errors sometimes cause this kind of errors.
-
-
-
-
- ATA/ATAPI device error (non-NCQ / non-CHECK CONDITION)
-
-
- These are errors detected and reported by ATA/ATAPI devices
- indicating device problems. For this type of errors, STATUS
- and ERROR register values are valid and describe error
- condition. Note that some of ATA bus errors are detected by
- ATA/ATAPI devices and reported using the same mechanism as
- device errors. Those cases are described later in this
- section.
-
-
-
- For ATA commands, this type of errors are indicated by !BSY
- && ERR during command execution and on completion.
-
-
- For ATAPI commands,
-
-
-
-
-
- !BSY && ERR && ABRT right after issuing PACKET
- indicates that PACKET command is not supported and falls in
- this category.
-
-
-
-
-
- !BSY && ERR(==CHK) && !ABRT after the last
- byte of CDB is transferred indicates CHECK CONDITION and
- doesn't fall in this category.
-
-
-
-
-
- !BSY && ERR(==CHK) && ABRT after the last byte
- of CDB is transferred *probably* indicates CHECK CONDITION and
- doesn't fall in this category.
-
-
-
-
-
-
- Of errors detected as above, the followings are not ATA/ATAPI
- device errors but ATA bus errors and should be handled
- according to .
-
-
-
-
-
- CRC error during data transfer
-
-
- This is indicated by ICRC bit in the ERROR register and
- means that corruption occurred during data transfer. Upto
- ATA/ATAPI-7, the standard specifies that this bit is only
- applicable to UDMA transfers but ATA/ATAPI-8 draft revision
- 1f says that the bit may be applicable to multiword DMA and
- PIO.
-
-
-
-
-
- ABRT error during data transfer or on completion
-
-
- Upto ATA/ATAPI-7, the standard specifies that ABRT could be
- set on ICRC errors and on cases where a device is not able
- to complete a command. Combined with the fact that MWDMA
- and PIO transfer errors aren't allowed to use ICRC bit upto
- ATA/ATAPI-7, it seems to imply that ABRT bit alone could
- indicate tranfer errors.
-
-
- However, ATA/ATAPI-8 draft revision 1f removes the part
- that ICRC errors can turn on ABRT. So, this is kind of
- gray area. Some heuristics are needed here.
-
-
-
-
-
-
-
- ATA/ATAPI device errors can be further categorized as follows.
-
-
-
-
-
- Media errors
-
-
- This is indicated by UNC bit in the ERROR register. ATA
- devices reports UNC error only after certain number of
- retries cannot recover the data, so there's nothing much
- else to do other than notifying upper layer.
-
-
- READ and WRITE commands report CHS or LBA of the first
- failed sector but ATA/ATAPI standard specifies that the
- amount of transferred data on error completion is
- indeterminate, so we cannot assume that sectors preceding
- the failed sector have been transferred and thus cannot
- complete those sectors successfully as SCSI does.
-
-
-
-
-
- Media changed / media change requested error
-
-
- <<TODO: fill here>>
-
-
-
-
- Address error
-
-
- This is indicated by IDNF bit in the ERROR register.
- Report to upper layer.
-
-
-
-
- Other errors
-
-
- This can be invalid command or parameter indicated by ABRT
- ERROR bit or some other error condition. Note that ABRT
- bit can indicate a lot of things including ICRC and Address
- errors. Heuristics needed.
-
-
-
-
-
-
-
- Depending on commands, not all STATUS/ERROR bits are
- applicable. These non-applicable bits are marked with
- "na" in the output descriptions but upto ATA/ATAPI-7
- no definition of "na" can be found. However,
- ATA/ATAPI-8 draft revision 1f describes "N/A" as
- follows.
-
-
-
-
- 3.2.3.3a N/A
-
-
- A keyword the indicates a field has no defined value in
- this standard and should not be checked by the host or
- device. N/A fields should be cleared to zero.
-
-
-
-
-
-
-
- So, it seems reasonable to assume that "na" bits are
- cleared to zero by devices and thus need no explicit masking.
-
-
-
-
-
- ATAPI device CHECK CONDITION
-
-
- ATAPI device CHECK CONDITION error is indicated by set CHK bit
- (ERR bit) in the STATUS register after the last byte of CDB is
- transferred for a PACKET command. For this kind of errors,
- sense data should be acquired to gather information regarding
- the errors. REQUEST SENSE packet command should be used to
- acquire sense data.
-
-
-
- Once sense data is acquired, this type of errors can be
- handled similary to other SCSI errors. Note that sense data
- may indicate ATA bus error (e.g. Sense Key 04h HARDWARE ERROR
- && ASC/ASCQ 47h/00h SCSI PARITY ERROR). In such
- cases, the error should be considered as an ATA bus error and
- handled according to .
-
-
-
-
-
- ATA device error (NCQ)
-
-
- NCQ command error is indicated by cleared BSY and set ERR bit
- during NCQ command phase (one or more NCQ commands
- outstanding). Although STATUS and ERROR registers will
- contain valid values describing the error, READ LOG EXT is
- required to clear the error condition, determine which command
- has failed and acquire more information.
-
-
-
- READ LOG EXT Log Page 10h reports which tag has failed and
- taskfile register values describing the error. With this
- information the failed command can be handled as a normal ATA
- command error as in and all
- other in-flight commands must be retried. Note that this
- retry should not be counted - it's likely that commands
- retried this way would have completed normally if it were not
- for the failed command.
-
-
-
- Note that ATA bus errors can be reported as ATA device NCQ
- errors. This should be handled as described in .
-
-
-
- If READ LOG EXT Log Page 10h fails or reports NQ, we're
- thoroughly screwed. This condition should be treated
- according to .
-
-
-
-
-
- ATA bus error
-
-
- ATA bus error means that data corruption occurred during
- transmission over ATA bus (SATA or PATA). This type of errors
- can be indicated by
-
-
-
-
-
-
- ICRC or ABRT error as described in .
-
-
-
-
-
- Controller-specific error completion with error information
- indicating transmission error.
-
-
-
-
-
- On some controllers, command timeout. In this case, there may
- be a mechanism to determine that the timeout is due to
- transmission error.
-
-
-
-
-
- Unknown/random errors, timeouts and all sorts of weirdities.
-
-
-
-
-
-
- As described above, transmission errors can cause wide variety
- of symptoms ranging from device ICRC error to random device
- lockup, and, for many cases, there is no way to tell if an
- error condition is due to transmission error or not;
- therefore, it's necessary to employ some kind of heuristic
- when dealing with errors and timeouts. For example,
- encountering repetitive ABRT errors for known supported
- command is likely to indicate ATA bus error.
-
-
-
- Once it's determined that ATA bus errors have possibly
- occurred, lowering ATA bus transmission speed is one of
- actions which may alleviate the problem. See for more information.
-
-
-
-
-
- PCI bus error
-
-
- Data corruption or other failures during transmission over PCI
- (or other system bus). For standard BMDMA, this is indicated
- by Error bit in the BMDMA Status register. This type of
- errors must be logged as it indicates something is very wrong
- with the system. Resetting host controller is recommended.
-
-
-
-
-
- Late completion
-
-
- This occurs when timeout occurs and the timeout handler finds
- out that the timed out command has completed successfully or
- with error. This is usually caused by lost interrupts. This
- type of errors must be logged. Resetting host controller is
- recommended.
-
-
-
-
-
- Unknown error (timeout)
-
-
- This is when timeout occurs and the command is still
- processing or the host and device are in unknown state. When
- this occurs, HSM could be in any valid or invalid state. To
- bring the device to known state and make it forget about the
- timed out command, resetting is necessary. The timed out
- command may be retried.
-
-
-
- Timeouts can also be caused by transmission errors. Refer to
- for more details.
-
-
-
-
-
- Hotplug and power management exceptions
-
-
- <<TODO: fill here>>
-
-
-
-
-
-
-
- EH recovery actions
-
-
- This section discusses several important recovery actions.
-
-
-
- Clearing error condition
-
-
- Many controllers require its error registers to be cleared by
- error handler. Different controllers may have different
- requirements.
-
-
-
- For SATA, it's strongly recommended to clear at least SError
- register during error handling.
-
-
-
-
- Reset
-
-
- During EH, resetting is necessary in the following cases.
-
-
-
-
-
-
- HSM is in unknown or invalid state
-
-
-
-
-
- HBA is in unknown or invalid state
-
-
-
-
-
- EH needs to make HBA/device forget about in-flight commands
-
-
-
-
-
- HBA/device behaves weirdly
-
-
-
-
-
-
- Resetting during EH might be a good idea regardless of error
- condition to improve EH robustness. Whether to reset both or
- either one of HBA and device depends on situation but the
- following scheme is recommended.
-
-
-
-
-
-
- When it's known that HBA is in ready state but ATA/ATAPI
- device in in unknown state, reset only device.
-
-
-
-
-
- If HBA is in unknown state, reset both HBA and device.
-
-
-
-
-
-
- HBA resetting is implementation specific. For a controller
- complying to taskfile/BMDMA PCI IDE, stopping active DMA
- transaction may be sufficient iff BMDMA state is the only HBA
- context. But even mostly taskfile/BMDMA PCI IDE complying
- controllers may have implementation specific requirements and
- mechanism to reset themselves. This must be addressed by
- specific drivers.
-
-
-
- OTOH, ATA/ATAPI standard describes in detail ways to reset
- ATA/ATAPI devices.
-
-
-
-
- PATA hardware reset
-
-
- This is hardware initiated device reset signalled with
- asserted PATA RESET- signal. There is no standard way to
- initiate hardware reset from software although some
- hardware provides registers that allow driver to directly
- tweak the RESET- signal.
-
-
-
-
- Software reset
-
-
- This is achieved by turning CONTROL SRST bit on for at
- least 5us. Both PATA and SATA support it but, in case of
- SATA, this may require controller-specific support as the
- second Register FIS to clear SRST should be transmitted
- while BSY bit is still set. Note that on PATA, this resets
- both master and slave devices on a channel.
-
-
-
-
- EXECUTE DEVICE DIAGNOSTIC command
-
-
- Although ATA/ATAPI standard doesn't describe exactly, EDD
- implies some level of resetting, possibly similar level
- with software reset. Host-side EDD protocol can be handled
- with normal command processing and most SATA controllers
- should be able to handle EDD's just like other commands.
- As in software reset, EDD affects both devices on a PATA
- bus.
-
-
- Although EDD does reset devices, this doesn't suit error
- handling as EDD cannot be issued while BSY is set and it's
- unclear how it will act when device is in unknown/weird
- state.
-
-
-
-
- ATAPI DEVICE RESET command
-
-
- This is very similar to software reset except that reset
- can be restricted to the selected device without affecting
- the other device sharing the cable.
-
-
-
-
- SATA phy reset
-
-
- This is the preferred way of resetting a SATA device. In
- effect, it's identical to PATA hardware reset. Note that
- this can be done with the standard SCR Control register.
- As such, it's usually easier to implement than software
- reset.
-
-
-
-
-
-
-
- One more thing to consider when resetting devices is that
- resetting clears certain configuration parameters and they
- need to be set to their previous or newly adjusted values
- after reset.
-
-
-
- Parameters affected are.
-
-
-
-
-
-
- CHS set up with INITIALIZE DEVICE PARAMETERS (seldomly used)
-
-
-
-
-
- Parameters set with SET FEATURES including transfer mode setting
-
-
-
-
-
- Block count set with SET MULTIPLE MODE
-
-
-
-
-
- Other parameters (SET MAX, MEDIA LOCK...)
-
-
-
-
-
-
- ATA/ATAPI standard specifies that some parameters must be
- maintained across hardware or software reset, but doesn't
- strictly specify all of them. Always reconfiguring needed
- parameters after reset is required for robustness. Note that
- this also applies when resuming from deep sleep (power-off).
-
-
-
- Also, ATA/ATAPI standard requires that IDENTIFY DEVICE /
- IDENTIFY PACKET DEVICE is issued after any configuration
- parameter is updated or a hardware reset and the result used
- for further operation. OS driver is required to implement
- revalidation mechanism to support this.
-
-
-
-
-
- Reconfigure transport
-
-
- For both PATA and SATA, a lot of corners are cut for cheap
- connectors, cables or controllers and it's quite common to see
- high transmission error rate. This can be mitigated by
- lowering transmission speed.
-
-
-
- The following is a possible scheme Jeff Garzik suggested.
-
-
-
-
- If more than $N (3?) transmission errors happen in 15 minutes,
-
-
-
-
- if SATA, decrease SATA PHY speed. if speed cannot be decreased,
-
-
-
-
- decrease UDMA xfer speed. if at UDMA0, switch to PIO4,
-
-
-
-
- decrease PIO xfer speed. if at PIO3, complain, but continue
-
-
-
-
-
-
-
-
-
-
-
ata_piix Internals
!Idrivers/scsi/ata_piix.c
diff --git a/trunk/Documentation/block/biodoc.txt b/trunk/Documentation/block/biodoc.txt
index 2d65c2182161..6dd274d7e1cf 100644
--- a/trunk/Documentation/block/biodoc.txt
+++ b/trunk/Documentation/block/biodoc.txt
@@ -906,20 +906,9 @@ Aside:
4. The I/O scheduler
-I/O scheduler, a.k.a. elevator, is implemented in two layers. Generic dispatch
-queue and specific I/O schedulers. Unless stated otherwise, elevator is used
-to refer to both parts and I/O scheduler to specific I/O schedulers.
-
-Block layer implements generic dispatch queue in ll_rw_blk.c and elevator.c.
-The generic dispatch queue is responsible for properly ordering barrier
-requests, requeueing, handling non-fs requests and all other subtleties.
-
-Specific I/O schedulers are responsible for ordering normal filesystem
-requests. They can also choose to delay certain requests to improve
-throughput or whatever purpose. As the plural form indicates, there are
-multiple I/O schedulers. They can be built as modules but at least one should
-be built inside the kernel. Each queue can choose different one and can also
-change to another one dynamically.
+I/O schedulers are now per queue. They should be runtime switchable and modular
+but aren't yet. Jens has most bits to do this, but the sysfs implementation is
+missing.
A block layer call to the i/o scheduler follows the convention elv_xxx(). This
calls elevator_xxx_fn in the elevator switch (drivers/block/elevator.c). Oh,
@@ -932,36 +921,44 @@ keeping work.
The functions an elevator may implement are: (* are mandatory)
elevator_merge_fn called to query requests for merge with a bio
-elevator_merge_req_fn called when two requests get merged. the one
- which gets merged into the other one will be
- never seen by I/O scheduler again. IOW, after
- being merged, the request is gone.
+elevator_merge_req_fn " " " with another request
elevator_merged_fn called when a request in the scheduler has been
involved in a merge. It is used in the deadline
scheduler for example, to reposition the request
if its sorting order has changed.
-elevator_dispatch_fn fills the dispatch queue with ready requests.
- I/O schedulers are free to postpone requests by
- not filling the dispatch queue unless @force
- is non-zero. Once dispatched, I/O schedulers
- are not allowed to manipulate the requests -
- they belong to generic dispatch queue.
+*elevator_next_req_fn returns the next scheduled request, or NULL
+ if there are none (or none are ready).
-elevator_add_req_fn called to add a new request into the scheduler
+*elevator_add_req_fn called to add a new request into the scheduler
elevator_queue_empty_fn returns true if the merge queue is empty.
Drivers shouldn't use this, but rather check
if elv_next_request is NULL (without losing the
request if one exists!)
+elevator_remove_req_fn This is called when a driver claims ownership of
+ the target request - it now belongs to the
+ driver. It must not be modified or merged.
+ Drivers must not lose the request! A subsequent
+ call of elevator_next_req_fn must return the
+ _next_ request.
+
+elevator_requeue_req_fn called to add a request to the scheduler. This
+ is used when the request has alrnadebeen
+ returned by elv_next_request, but hasn't
+ completed. If this is not implemented then
+ elevator_add_req_fn is called instead.
+
elevator_former_req_fn
elevator_latter_req_fn These return the request before or after the
one specified in disk sort order. Used by the
block layer to find merge possibilities.
-elevator_completed_req_fn called when a request is completed.
+elevator_completed_req_fn called when a request is completed. This might
+ come about due to being merged with another or
+ when the device completes the request.
elevator_may_queue_fn returns true if the scheduler wants to allow the
current context to queue a new request even if
@@ -970,33 +967,13 @@ elevator_may_queue_fn returns true if the scheduler wants to allow the
elevator_set_req_fn
elevator_put_req_fn Must be used to allocate and free any elevator
- specific storage for a request.
-
-elevator_activate_req_fn Called when device driver first sees a request.
- I/O schedulers can use this callback to
- determine when actual execution of a request
- starts.
-elevator_deactivate_req_fn Called when device driver decides to delay
- a request by requeueing it.
+ specific storate for a request.
elevator_init_fn
elevator_exit_fn Allocate and free any elevator specific storage
for a queue.
-4.2 Request flows seen by I/O schedulers
-All requests seens by I/O schedulers strictly follow one of the following three
-flows.
-
- set_req_fn ->
-
- i. add_req_fn -> (merged_fn ->)* -> dispatch_fn -> activate_req_fn ->
- (deactivate_req_fn -> activate_req_fn ->)* -> completed_req_fn
- ii. add_req_fn -> (merged_fn ->)* -> merge_req_fn
- iii. [none]
-
- -> put_req_fn
-
-4.3 I/O scheduler implementation
+4.2 I/O scheduler implementation
The generic i/o scheduler algorithm attempts to sort/merge/batch requests for
optimal disk scan and request servicing performance (based on generic
principles and device capabilities), optimized for:
@@ -1016,7 +993,18 @@ request in sort order to prevent binary tree lookups.
This arrangement is not a generic block layer characteristic however, so
elevators may implement queues as they please.
-ii. Merge hash
+ii. Last merge hint
+The last merge hint is part of the generic queue layer. I/O schedulers must do
+some management on it. For the most part, the most important thing is to make
+sure q->last_merge is cleared (set to NULL) when the request on it is no longer
+a candidate for merging (for example if it has been sent to the driver).
+
+The last merge performed is cached as a hint for the subsequent request. If
+sequential data is being submitted, the hint is used to perform merges without
+any scanning. This is not sufficient when there are multiple processes doing
+I/O though, so a "merge hash" is used by some schedulers.
+
+iii. Merge hash
AS and deadline use a hash table indexed by the last sector of a request. This
enables merging code to quickly look up "back merge" candidates, even when
multiple I/O streams are being performed at once on one disk.
@@ -1025,8 +1013,29 @@ multiple I/O streams are being performed at once on one disk.
are far less common than "back merges" due to the nature of most I/O patterns.
Front merges are handled by the binary trees in AS and deadline schedulers.
-iii. Plugging the queue to batch requests in anticipation of opportunities for
- merge/sort optimizations
+iv. Handling barrier cases
+A request with flags REQ_HARDBARRIER or REQ_SOFTBARRIER must not be ordered
+around. That is, they must be processed after all older requests, and before
+any newer ones. This includes merges!
+
+In AS and deadline schedulers, barriers have the effect of flushing the reorder
+queue. The performance cost of this will vary from nothing to a lot depending
+on i/o patterns and device characteristics. Obviously they won't improve
+performance, so their use should be kept to a minimum.
+
+v. Handling insertion position directives
+A request may be inserted with a position directive. The directives are one of
+ELEVATOR_INSERT_BACK, ELEVATOR_INSERT_FRONT, ELEVATOR_INSERT_SORT.
+
+ELEVATOR_INSERT_SORT is a general directive for non-barrier requests.
+ELEVATOR_INSERT_BACK is used to insert a barrier to the back of the queue.
+ELEVATOR_INSERT_FRONT is used to insert a barrier to the front of the queue, and
+overrides the ordering requested by any previous barriers. In practice this is
+harmless and required, because it is used for SCSI requeueing. This does not
+require flushing the reorder queue, so does not impose a performance penalty.
+
+vi. Plugging the queue to batch requests in anticipation of opportunities for
+ merge/sort optimizations
This is just the same as in 2.4 so far, though per-device unplugging
support is anticipated for 2.5. Also with a priority-based i/o scheduler,
@@ -1060,7 +1069,7 @@ Aside:
blk_kick_queue() to unplug a specific queue (right away ?)
or optionally, all queues, is in the plan.
-4.4 I/O contexts
+4.3 I/O contexts
I/O contexts provide a dynamically allocated per process data area. They may
be used in I/O schedulers, and in the block layer (could be used for IO statis,
priorities for example). See *io_context in drivers/block/ll_rw_blk.c, and
diff --git a/trunk/Documentation/networking/bonding.txt b/trunk/Documentation/networking/bonding.txt
index b0fe41da007b..a55f0f95b171 100644
--- a/trunk/Documentation/networking/bonding.txt
+++ b/trunk/Documentation/networking/bonding.txt
@@ -777,7 +777,7 @@ doing so is the same as described in the "Configuring Multiple Bonds
Manually" section, below.
NOTE: It has been observed that some Red Hat supplied kernels
-are apparently unable to rename modules at load time (the "-o bond1"
+are apparently unable to rename modules at load time (the "-obonding1"
part). Attempts to pass that option to modprobe will produce an
"Operation not permitted" error. This has been reported on some
Fedora Core kernels, and has been seen on RHEL 4 as well. On kernels
@@ -883,8 +883,7 @@ the above does not work, and the second bonding instance never sees
its options. In that case, the second options line can be substituted
as follows:
-install bond1 /sbin/modprobe --ignore-install bonding -o bond1 \
- mode=balance-alb miimon=50
+install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50
This may be repeated any number of times, specifying a new and
unique name in place of bond1 for each subsequent instance.
diff --git a/trunk/Makefile b/trunk/Makefile
index f1d121f23025..1fa7e5343464 100644
--- a/trunk/Makefile
+++ b/trunk/Makefile
@@ -334,7 +334,7 @@ KALLSYMS = scripts/kallsyms
PERL = perl
CHECK = sparse
-CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
+CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ $(CF)
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
diff --git a/trunk/arch/alpha/kernel/pci-noop.c b/trunk/arch/alpha/kernel/pci-noop.c
index 9903e3a79102..582a3519fb28 100644
--- a/trunk/arch/alpha/kernel/pci-noop.c
+++ b/trunk/arch/alpha/kernel/pci-noop.c
@@ -154,7 +154,7 @@ pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
void *
dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+ dma_addr_t *dma_handle, int gfp)
{
void *ret;
diff --git a/trunk/arch/alpha/kernel/pci_iommu.c b/trunk/arch/alpha/kernel/pci_iommu.c
index c468e312e5f8..7cb23f12ecbd 100644
--- a/trunk/arch/alpha/kernel/pci_iommu.c
+++ b/trunk/arch/alpha/kernel/pci_iommu.c
@@ -397,7 +397,7 @@ pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
{
void *cpu_addr;
long order = get_order(size);
- gfp_t gfp = GFP_ATOMIC;
+ int gfp = GFP_ATOMIC;
try_again:
cpu_addr = (void *)__get_free_pages(gfp, order);
diff --git a/trunk/arch/arm/mm/consistent.c b/trunk/arch/arm/mm/consistent.c
index 82f4d5e27c54..26356ce4da54 100644
--- a/trunk/arch/arm/mm/consistent.c
+++ b/trunk/arch/arm/mm/consistent.c
@@ -75,7 +75,7 @@ static struct vm_region consistent_head = {
};
static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
+vm_region_alloc(struct vm_region *head, size_t size, int gfp)
{
unsigned long addr = head->vm_start, end = head->vm_end - size;
unsigned long flags;
@@ -133,7 +133,7 @@ static struct vm_region *vm_region_find(struct vm_region *head, unsigned long ad
#endif
static void *
-__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
+__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
pgprot_t prot)
{
struct page *page;
@@ -251,7 +251,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
* virtual and bus address for that space.
*/
void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
{
return __dma_alloc(dev, size, handle, gfp,
pgprot_noncached(pgprot_kernel));
@@ -263,7 +263,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
* dma_alloc_coherent above.
*/
void *
-dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
{
return __dma_alloc(dev, size, handle, gfp,
pgprot_writecombine(pgprot_kernel));
diff --git a/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c b/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c
index 2082a9647f4f..819895cf0b9e 100644
--- a/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c
+++ b/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c
@@ -33,7 +33,7 @@ struct dma_alloc_record {
static DEFINE_SPINLOCK(dma_alloc_lock);
static LIST_HEAD(dma_alloc_list);
-void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
{
struct dma_alloc_record *new;
struct list_head *this = &dma_alloc_list;
diff --git a/trunk/arch/frv/mb93090-mb00/pci-dma.c b/trunk/arch/frv/mb93090-mb00/pci-dma.c
index 86fbdadc51b6..27eb12066507 100644
--- a/trunk/arch/frv/mb93090-mb00/pci-dma.c
+++ b/trunk/arch/frv/mb93090-mb00/pci-dma.c
@@ -17,7 +17,7 @@
#include
#include
-void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
{
void *ret;
diff --git a/trunk/arch/frv/mm/dma-alloc.c b/trunk/arch/frv/mm/dma-alloc.c
index cfc4f97490c6..4b38d45435f6 100644
--- a/trunk/arch/frv/mm/dma-alloc.c
+++ b/trunk/arch/frv/mm/dma-alloc.c
@@ -81,7 +81,7 @@ static int map_page(unsigned long va, unsigned long pa, pgprot_t prot)
* portions of the kernel with single large page TLB entries, and
* still get unique uncached pages for consistent DMA.
*/
-void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
{
struct vm_struct *area;
unsigned long page, va, pa;
diff --git a/trunk/arch/ia64/hp/common/hwsw_iommu.c b/trunk/arch/ia64/hp/common/hwsw_iommu.c
index 1ba02baf2f94..80f8ef013939 100644
--- a/trunk/arch/ia64/hp/common/hwsw_iommu.c
+++ b/trunk/arch/ia64/hp/common/hwsw_iommu.c
@@ -71,7 +71,7 @@ hwsw_init (void)
}
void *
-hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
+hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
{
if (use_swiotlb(dev))
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
diff --git a/trunk/arch/ia64/hp/common/sba_iommu.c b/trunk/arch/ia64/hp/common/sba_iommu.c
index 21bffba78b6d..11957598a8b9 100644
--- a/trunk/arch/ia64/hp/common/sba_iommu.c
+++ b/trunk/arch/ia64/hp/common/sba_iommu.c
@@ -1076,7 +1076,7 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
* See Documentation/DMA-mapping.txt
*/
void *
-sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
+sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
{
struct ioc *ioc;
void *addr;
diff --git a/trunk/arch/ia64/lib/swiotlb.c b/trunk/arch/ia64/lib/swiotlb.c
index 3ebbb3c8ba36..a604efc7f6c9 100644
--- a/trunk/arch/ia64/lib/swiotlb.c
+++ b/trunk/arch/ia64/lib/swiotlb.c
@@ -314,7 +314,7 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
void *
swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags)
+ dma_addr_t *dma_handle, int flags)
{
unsigned long dev_addr;
void *ret;
diff --git a/trunk/arch/ia64/sn/kernel/xpc.h b/trunk/arch/ia64/sn/kernel/xpc.h
index e5f5a4e51f70..d0ee635daf2e 100644
--- a/trunk/arch/ia64/sn/kernel/xpc.h
+++ b/trunk/arch/ia64/sn/kernel/xpc.h
@@ -939,7 +939,7 @@ xpc_map_bte_errors(bte_result_t error)
static inline void *
-xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+xpc_kmalloc_cacheline_aligned(size_t size, int flags, void **base)
{
/* see if kmalloc will give us cachline aligned memory by default */
*base = kmalloc(size, flags);
diff --git a/trunk/arch/ia64/sn/pci/pci_dma.c b/trunk/arch/ia64/sn/pci/pci_dma.c
index 75e6e874bebf..0e4b9ad9ef02 100644
--- a/trunk/arch/ia64/sn/pci/pci_dma.c
+++ b/trunk/arch/ia64/sn/pci/pci_dma.c
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(sn_dma_set_mask);
* more information.
*/
void *sn_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t flags)
+ dma_addr_t * dma_handle, int flags)
{
void *cpuaddr;
unsigned long phys_addr;
diff --git a/trunk/arch/mips/mm/dma-coherent.c b/trunk/arch/mips/mm/dma-coherent.c
index a617f8c327e8..97a50d38c98f 100644
--- a/trunk/arch/mips/mm/dma-coherent.c
+++ b/trunk/arch/mips/mm/dma-coherent.c
@@ -18,7 +18,7 @@
#include
void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
{
void *ret;
/* ignore region specifiers */
@@ -39,7 +39,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
EXPORT_SYMBOL(dma_alloc_noncoherent);
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
__attribute__((alias("dma_alloc_noncoherent")));
EXPORT_SYMBOL(dma_alloc_coherent);
diff --git a/trunk/arch/mips/mm/dma-ip27.c b/trunk/arch/mips/mm/dma-ip27.c
index 8da19fd22ac6..aa7c94b5d781 100644
--- a/trunk/arch/mips/mm/dma-ip27.c
+++ b/trunk/arch/mips/mm/dma-ip27.c
@@ -22,7 +22,7 @@
pdev_to_baddr(to_pci_dev(dev), (addr))
void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
{
void *ret;
@@ -44,7 +44,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
EXPORT_SYMBOL(dma_alloc_noncoherent);
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
__attribute__((alias("dma_alloc_noncoherent")));
EXPORT_SYMBOL(dma_alloc_coherent);
diff --git a/trunk/arch/mips/mm/dma-ip32.c b/trunk/arch/mips/mm/dma-ip32.c
index a7e3072ff78d..2cbe196c35fb 100644
--- a/trunk/arch/mips/mm/dma-ip32.c
+++ b/trunk/arch/mips/mm/dma-ip32.c
@@ -37,7 +37,7 @@
#define RAM_OFFSET_MASK 0x3fffffff
void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
{
void *ret;
/* ignore region specifiers */
@@ -61,7 +61,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
EXPORT_SYMBOL(dma_alloc_noncoherent);
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
{
void *ret;
diff --git a/trunk/arch/mips/mm/dma-noncoherent.c b/trunk/arch/mips/mm/dma-noncoherent.c
index 4ce02028a292..59e54f12212e 100644
--- a/trunk/arch/mips/mm/dma-noncoherent.c
+++ b/trunk/arch/mips/mm/dma-noncoherent.c
@@ -24,7 +24,7 @@
*/
void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
{
void *ret;
/* ignore region specifiers */
@@ -45,7 +45,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
EXPORT_SYMBOL(dma_alloc_noncoherent);
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, int gfp)
{
void *ret;
diff --git a/trunk/arch/parisc/kernel/pci-dma.c b/trunk/arch/parisc/kernel/pci-dma.c
index 844c2877a2e3..368cc095c99f 100644
--- a/trunk/arch/parisc/kernel/pci-dma.c
+++ b/trunk/arch/parisc/kernel/pci-dma.c
@@ -349,7 +349,7 @@ pcxl_dma_init(void)
__initcall(pcxl_dma_init);
-static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
+static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
{
unsigned long vaddr;
unsigned long paddr;
@@ -502,13 +502,13 @@ struct hppa_dma_ops pcxl_dma_ops = {
};
static void *fail_alloc_consistent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, int flag)
{
return NULL;
}
static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, int flag)
{
void *addr = NULL;
diff --git a/trunk/arch/ppc/8xx_io/cs4218.h b/trunk/arch/ppc/8xx_io/cs4218.h
index f1c7392255f8..a3c38c5a5db2 100644
--- a/trunk/arch/ppc/8xx_io/cs4218.h
+++ b/trunk/arch/ppc/8xx_io/cs4218.h
@@ -78,7 +78,7 @@ typedef struct {
const char *name2;
void (*open)(void);
void (*release)(void);
- void *(*dma_alloc)(unsigned int, gfp_t);
+ void *(*dma_alloc)(unsigned int, int);
void (*dma_free)(void *, unsigned int);
int (*irqinit)(void);
#ifdef MODULE
diff --git a/trunk/arch/ppc/8xx_io/cs4218_tdm.c b/trunk/arch/ppc/8xx_io/cs4218_tdm.c
index 532caa388dc2..2ca9ec7ec3a7 100644
--- a/trunk/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/trunk/arch/ppc/8xx_io/cs4218_tdm.c
@@ -318,7 +318,7 @@ struct cs_sound_settings {
static struct cs_sound_settings sound;
-static void *CS_Alloc(unsigned int size, gfp_t flags);
+static void *CS_Alloc(unsigned int size, int flags);
static void CS_Free(void *ptr, unsigned int size);
static int CS_IrqInit(void);
#ifdef MODULE
@@ -959,7 +959,7 @@ static TRANS transCSNormalRead = {
/*** Low level stuff *********************************************************/
-static void *CS_Alloc(unsigned int size, gfp_t flags)
+static void *CS_Alloc(unsigned int size, int flags)
{
int order;
diff --git a/trunk/arch/ppc/kernel/dma-mapping.c b/trunk/arch/ppc/kernel/dma-mapping.c
index 0f710d2baec6..8edee806dae7 100644
--- a/trunk/arch/ppc/kernel/dma-mapping.c
+++ b/trunk/arch/ppc/kernel/dma-mapping.c
@@ -115,7 +115,7 @@ static struct vm_region consistent_head = {
};
static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
+vm_region_alloc(struct vm_region *head, size_t size, int gfp)
{
unsigned long addr = head->vm_start, end = head->vm_end - size;
unsigned long flags;
@@ -173,7 +173,7 @@ static struct vm_region *vm_region_find(struct vm_region *head, unsigned long ad
* virtual and bus address for that space.
*/
void *
-__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
+__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp)
{
struct page *page;
struct vm_region *c;
diff --git a/trunk/arch/ppc/mm/pgtable.c b/trunk/arch/ppc/mm/pgtable.c
index 43505b1fc5d8..81a3d7446d37 100644
--- a/trunk/arch/ppc/mm/pgtable.c
+++ b/trunk/arch/ppc/mm/pgtable.c
@@ -114,9 +114,9 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
struct page *ptepage;
#ifdef CONFIG_HIGHPTE
- gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+ int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
#else
- gfp_t flags = GFP_KERNEL | __GFP_REPEAT;
+ int flags = GFP_KERNEL | __GFP_REPEAT;
#endif
ptepage = alloc_pages(flags, 0);
diff --git a/trunk/arch/sh/boards/renesas/rts7751r2d/mach.c b/trunk/arch/sh/boards/renesas/rts7751r2d/mach.c
index 610740512d56..1efc18e786d5 100644
--- a/trunk/arch/sh/boards/renesas/rts7751r2d/mach.c
+++ b/trunk/arch/sh/boards/renesas/rts7751r2d/mach.c
@@ -23,7 +23,7 @@ extern void init_rts7751r2d_IRQ(void);
extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
extern int rts7751r2d_irq_demux(int irq);
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
+extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
/*
diff --git a/trunk/arch/sh/cchips/voyagergx/consistent.c b/trunk/arch/sh/cchips/voyagergx/consistent.c
index 3d9a02c093a3..5b92585a38d2 100644
--- a/trunk/arch/sh/cchips/voyagergx/consistent.c
+++ b/trunk/arch/sh/cchips/voyagergx/consistent.c
@@ -31,7 +31,7 @@ static LIST_HEAD(voya_alloc_list);
#define OHCI_SRAM_SIZE 0x10000
void *voyagergx_consistent_alloc(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t flag)
+ dma_addr_t *handle, int flag)
{
struct list_head *list = &voya_alloc_list;
struct voya_alloc_entry *entry;
diff --git a/trunk/arch/sh/drivers/pci/dma-dreamcast.c b/trunk/arch/sh/drivers/pci/dma-dreamcast.c
index e12418bb1fa5..83de7ef4e7df 100644
--- a/trunk/arch/sh/drivers/pci/dma-dreamcast.c
+++ b/trunk/arch/sh/drivers/pci/dma-dreamcast.c
@@ -33,7 +33,7 @@
static int gapspci_dma_used = 0;
void *dreamcast_consistent_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, int flag)
{
unsigned long buf;
diff --git a/trunk/arch/sh/mm/consistent.c b/trunk/arch/sh/mm/consistent.c
index df3a9e452cc5..1f7af0c73cf4 100644
--- a/trunk/arch/sh/mm/consistent.c
+++ b/trunk/arch/sh/mm/consistent.c
@@ -11,7 +11,7 @@
#include
#include
-void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle)
{
struct page *page, *end, *free;
void *ret;
diff --git a/trunk/arch/sparc64/solaris/socksys.c b/trunk/arch/sparc64/solaris/socksys.c
index fc6669e8dde1..d7c1c76582cc 100644
--- a/trunk/arch/sparc64/solaris/socksys.c
+++ b/trunk/arch/sparc64/solaris/socksys.c
@@ -49,7 +49,7 @@ IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
#else
-extern void * mykmalloc(size_t s, gfp_t gfp);
+extern void * mykmalloc(size_t s, int gfp);
extern void mykfree(void *);
#endif
diff --git a/trunk/arch/sparc64/solaris/timod.c b/trunk/arch/sparc64/solaris/timod.c
index b84e5456b025..aaad29c35c83 100644
--- a/trunk/arch/sparc64/solaris/timod.c
+++ b/trunk/arch/sparc64/solaris/timod.c
@@ -39,7 +39,7 @@ static char * page = NULL ;
#else
-void * mykmalloc(size_t s, gfp_t gfp)
+void * mykmalloc(size_t s, int gfp)
{
static char * page;
static size_t free;
diff --git a/trunk/arch/um/kernel/mem.c b/trunk/arch/um/kernel/mem.c
index 462cc9d65386..ea008b031a8f 100644
--- a/trunk/arch/um/kernel/mem.c
+++ b/trunk/arch/um/kernel/mem.c
@@ -252,7 +252,7 @@ void paging_init(void)
#endif
}
-struct page *arch_validate(struct page *page, gfp_t mask, int order)
+struct page *arch_validate(struct page *page, int mask, int order)
{
unsigned long addr, zero = 0;
int i;
diff --git a/trunk/arch/um/kernel/process_kern.c b/trunk/arch/um/kernel/process_kern.c
index 0d73ceeece72..ea65db679e9c 100644
--- a/trunk/arch/um/kernel/process_kern.c
+++ b/trunk/arch/um/kernel/process_kern.c
@@ -80,7 +80,7 @@ void free_stack(unsigned long stack, int order)
unsigned long alloc_stack(int order, int atomic)
{
unsigned long page;
- gfp_t flags = GFP_KERNEL;
+ int flags = GFP_KERNEL;
if (atomic)
flags = GFP_ATOMIC;
diff --git a/trunk/arch/x86_64/kernel/pci-gart.c b/trunk/arch/x86_64/kernel/pci-gart.c
index 88be97c96987..cf0a0315d586 100644
--- a/trunk/arch/x86_64/kernel/pci-gart.c
+++ b/trunk/arch/x86_64/kernel/pci-gart.c
@@ -187,7 +187,7 @@ static void flush_gart(struct device *dev)
/* Allocate DMA memory on node near device */
noinline
-static void *dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
+static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
{
struct page *page;
int node;
@@ -204,7 +204,7 @@ static void *dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
*/
void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp)
+ unsigned gfp)
{
void *memory;
unsigned long dma_mask = 0;
diff --git a/trunk/arch/x86_64/kernel/pci-nommu.c b/trunk/arch/x86_64/kernel/pci-nommu.c
index 5a981dca87ff..67d90b89af0b 100644
--- a/trunk/arch/x86_64/kernel/pci-nommu.c
+++ b/trunk/arch/x86_64/kernel/pci-nommu.c
@@ -24,7 +24,7 @@ EXPORT_SYMBOL(iommu_sac_force);
*/
void *dma_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+ dma_addr_t *dma_handle, unsigned gfp)
{
void *ret;
u64 mask;
diff --git a/trunk/arch/xtensa/kernel/pci-dma.c b/trunk/arch/xtensa/kernel/pci-dma.c
index 1ff82268e8ea..84fde258cf85 100644
--- a/trunk/arch/xtensa/kernel/pci-dma.c
+++ b/trunk/arch/xtensa/kernel/pci-dma.c
@@ -29,7 +29,7 @@
*/
void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
{
void *ret;
diff --git a/trunk/drivers/block/as-iosched.c b/trunk/drivers/block/as-iosched.c
index 4081c36c8c19..95c0a3690b0f 100644
--- a/trunk/drivers/block/as-iosched.c
+++ b/trunk/drivers/block/as-iosched.c
@@ -98,6 +98,7 @@ struct as_data {
struct as_rq *next_arq[2]; /* next in sort order */
sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */
+ struct list_head *dispatch; /* driver dispatch queue */
struct list_head *hash; /* request hash */
unsigned long exit_prob; /* probability a task will exit while
@@ -238,25 +239,6 @@ static struct io_context *as_get_io_context(void)
return ioc;
}
-static void as_put_io_context(struct as_rq *arq)
-{
- struct as_io_context *aic;
-
- if (unlikely(!arq->io_context))
- return;
-
- aic = arq->io_context->aic;
-
- if (arq->is_sync == REQ_SYNC && aic) {
- spin_lock(&aic->lock);
- set_bit(AS_TASK_IORUNNING, &aic->state);
- aic->last_end_request = jiffies;
- spin_unlock(&aic->lock);
- }
-
- put_io_context(arq->io_context);
-}
-
/*
* the back merge hash support functions
*/
@@ -279,6 +261,14 @@ static inline void as_del_arq_hash(struct as_rq *arq)
__as_del_arq_hash(arq);
}
+static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq)
+{
+ as_del_arq_hash(arq);
+
+ if (q->last_merge == arq->request)
+ q->last_merge = NULL;
+}
+
static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
{
struct request *rq = arq->request;
@@ -322,7 +312,7 @@ static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
BUG_ON(!arq->on_hash);
if (!rq_mergeable(__rq)) {
- as_del_arq_hash(arq);
+ as_remove_merge_hints(ad->q, arq);
continue;
}
@@ -960,12 +950,23 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
WARN_ON(!list_empty(&rq->queuelist));
+ if (arq->state == AS_RQ_PRESCHED) {
+ WARN_ON(arq->io_context);
+ goto out;
+ }
+
+ if (arq->state == AS_RQ_MERGED)
+ goto out_ioc;
+
if (arq->state != AS_RQ_REMOVED) {
printk("arq->state %d\n", arq->state);
WARN_ON(1);
goto out;
}
+ if (!blk_fs_request(rq))
+ goto out;
+
if (ad->changed_batch && ad->nr_dispatched == 1) {
kblockd_schedule_work(&ad->antic_work);
ad->changed_batch = 0;
@@ -1000,7 +1001,21 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
}
}
- as_put_io_context(arq);
+out_ioc:
+ if (!arq->io_context)
+ goto out;
+
+ if (arq->is_sync == REQ_SYNC) {
+ struct as_io_context *aic = arq->io_context->aic;
+ if (aic) {
+ spin_lock(&aic->lock);
+ set_bit(AS_TASK_IORUNNING, &aic->state);
+ aic->last_end_request = jiffies;
+ spin_unlock(&aic->lock);
+ }
+ }
+
+ put_io_context(arq->io_context);
out:
arq->state = AS_RQ_POSTSCHED;
}
@@ -1032,10 +1047,72 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq)
ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
list_del_init(&arq->fifo);
- as_del_arq_hash(arq);
+ as_remove_merge_hints(q, arq);
as_del_arq_rb(ad, arq);
}
+/*
+ * as_remove_dispatched_request is called to remove a request which has gone
+ * to the dispatch list.
+ */
+static void as_remove_dispatched_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ struct as_io_context *aic;
+
+ if (!arq) {
+ WARN_ON(1);
+ return;
+ }
+
+ WARN_ON(arq->state != AS_RQ_DISPATCHED);
+ WARN_ON(ON_RB(&arq->rb_node));
+ if (arq->io_context && arq->io_context->aic) {
+ aic = arq->io_context->aic;
+ if (aic) {
+ WARN_ON(!atomic_read(&aic->nr_dispatched));
+ atomic_dec(&aic->nr_dispatched);
+ }
+ }
+}
+
+/*
+ * as_remove_request is called when a driver has finished with a request.
+ * This should be only called for dispatched requests, but for some reason
+ * a POWER4 box running hwscan it does not.
+ */
+static void as_remove_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+
+ if (unlikely(arq->state == AS_RQ_NEW))
+ goto out;
+
+ if (ON_RB(&arq->rb_node)) {
+ if (arq->state != AS_RQ_QUEUED) {
+ printk("arq->state %d\n", arq->state);
+ WARN_ON(1);
+ goto out;
+ }
+ /*
+ * We'll lose the aliased request(s) here. I don't think this
+ * will ever happen, but if it does, hopefully someone will
+ * report it.
+ */
+ WARN_ON(!list_empty(&rq->queuelist));
+ as_remove_queued_request(q, rq);
+ } else {
+ if (arq->state != AS_RQ_DISPATCHED) {
+ printk("arq->state %d\n", arq->state);
+ WARN_ON(1);
+ goto out;
+ }
+ as_remove_dispatched_request(q, rq);
+ }
+out:
+ arq->state = AS_RQ_REMOVED;
+}
+
/*
* as_fifo_expired returns 0 if there are no expired reads on the fifo,
* 1 otherwise. It is ratelimited so that we only perform the check once per
@@ -1088,6 +1165,7 @@ static inline int as_batch_expired(struct as_data *ad)
static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
{
struct request *rq = arq->request;
+ struct list_head *insert;
const int data_dir = arq->is_sync;
BUG_ON(!ON_RB(&arq->rb_node));
@@ -1120,13 +1198,13 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
/*
* take it off the sort and fifo list, add to dispatch queue
*/
+ insert = ad->dispatch->prev;
+
while (!list_empty(&rq->queuelist)) {
struct request *__rq = list_entry_rq(rq->queuelist.next);
struct as_rq *__arq = RQ_DATA(__rq);
- list_del(&__rq->queuelist);
-
- elv_dispatch_add_tail(ad->q, __rq);
+ list_move_tail(&__rq->queuelist, ad->dispatch);
if (__arq->io_context && __arq->io_context->aic)
atomic_inc(&__arq->io_context->aic->nr_dispatched);
@@ -1140,8 +1218,7 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
as_remove_queued_request(ad->q, rq);
WARN_ON(arq->state != AS_RQ_QUEUED);
- elv_dispatch_sort(ad->q, rq);
-
+ list_add(&rq->queuelist, insert);
arq->state = AS_RQ_DISPATCHED;
if (arq->io_context && arq->io_context->aic)
atomic_inc(&arq->io_context->aic->nr_dispatched);
@@ -1153,42 +1230,12 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
* read/write expire, batch expire, etc, and moves it to the dispatch
* queue. Returns 1 if a request was found, 0 otherwise.
*/
-static int as_dispatch_request(request_queue_t *q, int force)
+static int as_dispatch_request(struct as_data *ad)
{
- struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq;
const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
- if (unlikely(force)) {
- /*
- * Forced dispatch, accounting is useless. Reset
- * accounting states and dump fifo_lists. Note that
- * batch_data_dir is reset to REQ_SYNC to avoid
- * screwing write batch accounting as write batch
- * accounting occurs on W->R transition.
- */
- int dispatched = 0;
-
- ad->batch_data_dir = REQ_SYNC;
- ad->changed_batch = 0;
- ad->new_batch = 0;
-
- while (ad->next_arq[REQ_SYNC]) {
- as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
- dispatched++;
- }
- ad->last_check_fifo[REQ_SYNC] = jiffies;
-
- while (ad->next_arq[REQ_ASYNC]) {
- as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
- dispatched++;
- }
- ad->last_check_fifo[REQ_ASYNC] = jiffies;
-
- return dispatched;
- }
-
/* Signal that the write batch was uncontended, so we can't time it */
if (ad->batch_data_dir == REQ_ASYNC && !reads) {
if (ad->current_write_count == 0 || !writes)
@@ -1312,6 +1359,20 @@ static int as_dispatch_request(request_queue_t *q, int force)
return 1;
}
+static struct request *as_next_request(request_queue_t *q)
+{
+ struct as_data *ad = q->elevator->elevator_data;
+ struct request *rq = NULL;
+
+ /*
+ * if there are still requests on the dispatch queue, grab the first
+ */
+ if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
+ rq = list_entry_rq(ad->dispatch->next);
+
+ return rq;
+}
+
/*
* Add arq to a list behind alias
*/
@@ -1343,25 +1404,17 @@ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alia
/*
* Don't want to have to handle merges.
*/
- as_del_arq_hash(arq);
+ as_remove_merge_hints(ad->q, arq);
}
/*
* add arq to rbtree and fifo
*/
-static void as_add_request(request_queue_t *q, struct request *rq)
+static void as_add_request(struct as_data *ad, struct as_rq *arq)
{
- struct as_data *ad = q->elevator->elevator_data;
- struct as_rq *arq = RQ_DATA(rq);
struct as_rq *alias;
int data_dir;
- if (arq->state != AS_RQ_PRESCHED) {
- printk("arq->state: %d\n", arq->state);
- WARN_ON(1);
- }
- arq->state = AS_RQ_NEW;
-
if (rq_data_dir(arq->request) == READ
|| current->flags&PF_SYNCWRITE)
arq->is_sync = 1;
@@ -1384,8 +1437,12 @@ static void as_add_request(request_queue_t *q, struct request *rq)
arq->expires = jiffies + ad->fifo_expire[data_dir];
list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
- if (rq_mergeable(arq->request))
+ if (rq_mergeable(arq->request)) {
as_add_arq_hash(ad, arq);
+
+ if (!ad->q->last_merge)
+ ad->q->last_merge = arq->request;
+ }
as_update_arq(ad, arq); /* keep state machine up to date */
} else {
@@ -1406,24 +1463,96 @@ static void as_add_request(request_queue_t *q, struct request *rq)
arq->state = AS_RQ_QUEUED;
}
-static void as_activate_request(request_queue_t *q, struct request *rq)
+static void as_deactivate_request(request_queue_t *q, struct request *rq)
{
+ struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- WARN_ON(arq->state != AS_RQ_DISPATCHED);
- arq->state = AS_RQ_REMOVED;
- if (arq->io_context && arq->io_context->aic)
- atomic_dec(&arq->io_context->aic->nr_dispatched);
+ if (arq) {
+ if (arq->state == AS_RQ_REMOVED) {
+ arq->state = AS_RQ_DISPATCHED;
+ if (arq->io_context && arq->io_context->aic)
+ atomic_inc(&arq->io_context->aic->nr_dispatched);
+ }
+ } else
+ WARN_ON(blk_fs_request(rq)
+ && (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
+
+ /* Stop anticipating - let this request get through */
+ as_antic_stop(ad);
}
-static void as_deactivate_request(request_queue_t *q, struct request *rq)
+/*
+ * requeue the request. The request has not been completed, nor is it a
+ * new request, so don't touch accounting.
+ */
+static void as_requeue_request(request_queue_t *q, struct request *rq)
+{
+ as_deactivate_request(q, rq);
+ list_add(&rq->queuelist, &q->queue_head);
+}
+
+/*
+ * Account a request that is inserted directly onto the dispatch queue.
+ * arq->io_context->aic->nr_dispatched should not need to be incremented
+ * because only new requests should come through here: requeues go through
+ * our explicit requeue handler.
+ */
+static void as_account_queued_request(struct as_data *ad, struct request *rq)
{
+ if (blk_fs_request(rq)) {
+ struct as_rq *arq = RQ_DATA(rq);
+ arq->state = AS_RQ_DISPATCHED;
+ ad->nr_dispatched++;
+ }
+}
+
+static void
+as_insert_request(request_queue_t *q, struct request *rq, int where)
+{
+ struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- WARN_ON(arq->state != AS_RQ_REMOVED);
- arq->state = AS_RQ_DISPATCHED;
- if (arq->io_context && arq->io_context->aic)
- atomic_inc(&arq->io_context->aic->nr_dispatched);
+ if (arq) {
+ if (arq->state != AS_RQ_PRESCHED) {
+ printk("arq->state: %d\n", arq->state);
+ WARN_ON(1);
+ }
+ arq->state = AS_RQ_NEW;
+ }
+
+ /* barriers must flush the reorder queue */
+ if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
+ && where == ELEVATOR_INSERT_SORT)) {
+ WARN_ON(1);
+ where = ELEVATOR_INSERT_BACK;
+ }
+
+ switch (where) {
+ case ELEVATOR_INSERT_BACK:
+ while (ad->next_arq[REQ_SYNC])
+ as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+
+ while (ad->next_arq[REQ_ASYNC])
+ as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+
+ list_add_tail(&rq->queuelist, ad->dispatch);
+ as_account_queued_request(ad, rq);
+ as_antic_stop(ad);
+ break;
+ case ELEVATOR_INSERT_FRONT:
+ list_add(&rq->queuelist, ad->dispatch);
+ as_account_queued_request(ad, rq);
+ as_antic_stop(ad);
+ break;
+ case ELEVATOR_INSERT_SORT:
+ BUG_ON(!blk_fs_request(rq));
+ as_add_request(ad, arq);
+ break;
+ default:
+ BUG();
+ return;
+ }
}
/*
@@ -1436,8 +1565,12 @@ static int as_queue_empty(request_queue_t *q)
{
struct as_data *ad = q->elevator->elevator_data;
- return list_empty(&ad->fifo_list[REQ_ASYNC])
- && list_empty(&ad->fifo_list[REQ_SYNC]);
+ if (!list_empty(&ad->fifo_list[REQ_ASYNC])
+ || !list_empty(&ad->fifo_list[REQ_SYNC])
+ || !list_empty(ad->dispatch))
+ return 0;
+
+ return 1;
}
static struct request *
@@ -1474,6 +1607,15 @@ as_merge(request_queue_t *q, struct request **req, struct bio *bio)
struct request *__rq;
int ret;
+ /*
+ * try last_merge to avoid going to hash
+ */
+ ret = elv_try_last_merge(q, bio);
+ if (ret != ELEVATOR_NO_MERGE) {
+ __rq = q->last_merge;
+ goto out_insert;
+ }
+
/*
* see if the merge hash can satisfy a back merge
*/
@@ -1502,6 +1644,9 @@ as_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
+ if (rq_mergeable(__rq))
+ q->last_merge = __rq;
+out_insert:
if (ret) {
if (rq_mergeable(__rq))
as_hot_arq_hash(ad, RQ_DATA(__rq));
@@ -1548,6 +1693,9 @@ static void as_merged_request(request_queue_t *q, struct request *req)
* behind the disk head. We currently don't bother adjusting.
*/
}
+
+ if (arq->on_hash)
+ q->last_merge = req;
}
static void
@@ -1615,7 +1763,6 @@ as_merged_requests(request_queue_t *q, struct request *req,
* kill knowledge of next, this one is a goner
*/
as_remove_queued_request(q, next);
- as_put_io_context(anext);
anext->state = AS_RQ_MERGED;
}
@@ -1635,7 +1782,7 @@ static void as_work_handler(void *data)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
- if (!as_queue_empty(q))
+ if (as_next_request(q))
q->request_fn(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
@@ -1650,9 +1797,7 @@ static void as_put_request(request_queue_t *q, struct request *rq)
return;
}
- if (unlikely(arq->state != AS_RQ_POSTSCHED &&
- arq->state != AS_RQ_PRESCHED &&
- arq->state != AS_RQ_MERGED)) {
+ if (arq->state != AS_RQ_POSTSCHED && arq->state != AS_RQ_PRESCHED) {
printk("arq->state %d\n", arq->state);
WARN_ON(1);
}
@@ -1662,7 +1807,7 @@ static void as_put_request(request_queue_t *q, struct request *rq)
}
static int as_set_request(request_queue_t *q, struct request *rq,
- struct bio *bio, gfp_t gfp_mask)
+ struct bio *bio, int gfp_mask)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
@@ -1762,6 +1907,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
ad->sort_list[REQ_SYNC] = RB_ROOT;
ad->sort_list[REQ_ASYNC] = RB_ROOT;
+ ad->dispatch = &q->queue_head;
ad->fifo_expire[REQ_SYNC] = default_read_expire;
ad->fifo_expire[REQ_ASYNC] = default_write_expire;
ad->antic_expire = default_antic_expire;
@@ -1926,9 +2072,10 @@ static struct elevator_type iosched_as = {
.elevator_merge_fn = as_merge,
.elevator_merged_fn = as_merged_request,
.elevator_merge_req_fn = as_merged_requests,
- .elevator_dispatch_fn = as_dispatch_request,
- .elevator_add_req_fn = as_add_request,
- .elevator_activate_req_fn = as_activate_request,
+ .elevator_next_req_fn = as_next_request,
+ .elevator_add_req_fn = as_insert_request,
+ .elevator_remove_req_fn = as_remove_request,
+ .elevator_requeue_req_fn = as_requeue_request,
.elevator_deactivate_req_fn = as_deactivate_request,
.elevator_queue_empty_fn = as_queue_empty,
.elevator_completed_req_fn = as_completed_request,
diff --git a/trunk/drivers/block/cfq-iosched.c b/trunk/drivers/block/cfq-iosched.c
index 94690e4d41e0..cd056e7e64ec 100644
--- a/trunk/drivers/block/cfq-iosched.c
+++ b/trunk/drivers/block/cfq-iosched.c
@@ -84,6 +84,7 @@ static int cfq_max_depth = 2;
(node)->rb_left = NULL; \
} while (0)
#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL)
+#define ON_RB(node) ((node)->rb_color != RB_NONE)
#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node)
#define rq_rb_key(rq) (rq)->sector
@@ -270,7 +271,10 @@ CFQ_CFQQ_FNS(expired);
#undef CFQ_CFQQ_FNS
enum cfq_rq_state_flags {
- CFQ_CRQ_FLAG_is_sync = 0,
+ CFQ_CRQ_FLAG_in_flight = 0,
+ CFQ_CRQ_FLAG_in_driver,
+ CFQ_CRQ_FLAG_is_sync,
+ CFQ_CRQ_FLAG_requeued,
};
#define CFQ_CRQ_FNS(name) \
@@ -287,11 +291,14 @@ static inline int cfq_crq_##name(const struct cfq_rq *crq) \
return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \
}
+CFQ_CRQ_FNS(in_flight);
+CFQ_CRQ_FNS(in_driver);
CFQ_CRQ_FNS(is_sync);
+CFQ_CRQ_FNS(requeued);
#undef CFQ_CRQ_FNS
static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
-static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
+static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
static void cfq_put_cfqd(struct cfq_data *cfqd);
#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE)
@@ -304,6 +311,14 @@ static inline void cfq_del_crq_hash(struct cfq_rq *crq)
hlist_del_init(&crq->hash);
}
+static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
+{
+ cfq_del_crq_hash(crq);
+
+ if (q->last_merge == crq->request)
+ q->last_merge = NULL;
+}
+
static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
{
const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
@@ -332,13 +347,18 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
return NULL;
}
+static inline int cfq_pending_requests(struct cfq_data *cfqd)
+{
+ return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues;
+}
+
/*
* scheduler run of queue, if there are requests pending and no one in the
* driver that will restart queueing
*/
static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
{
- if (!cfqd->rq_in_driver && cfqd->busy_queues)
+ if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd))
kblockd_schedule_work(&cfqd->unplug_work);
}
@@ -346,7 +366,7 @@ static int cfq_queue_empty(request_queue_t *q)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- return !cfqd->busy_queues;
+ return !cfq_pending_requests(cfqd);
}
/*
@@ -366,6 +386,11 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
if (crq2 == NULL)
return crq1;
+ if (cfq_crq_requeued(crq1) && !cfq_crq_requeued(crq2))
+ return crq1;
+ else if (cfq_crq_requeued(crq2) && !cfq_crq_requeued(crq1))
+ return crq2;
+
if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
return crq1;
else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
@@ -436,7 +461,10 @@ cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
struct rb_node *rbnext, *rbprev;
- if (!(rbnext = rb_next(&last->rb_node))) {
+ rbnext = NULL;
+ if (ON_RB(&last->rb_node))
+ rbnext = rb_next(&last->rb_node);
+ if (!rbnext) {
rbnext = rb_first(&cfqq->sort_list);
if (rbnext == &last->rb_node)
rbnext = NULL;
@@ -517,13 +545,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
* the pending list according to last request service
*/
static inline void
-cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue)
{
BUG_ON(cfq_cfqq_on_rr(cfqq));
cfq_mark_cfqq_on_rr(cfqq);
cfqd->busy_queues++;
- cfq_resort_rr_list(cfqq, 0);
+ cfq_resort_rr_list(cfqq, requeue);
}
static inline void
@@ -543,19 +571,22 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
static inline void cfq_del_crq_rb(struct cfq_rq *crq)
{
struct cfq_queue *cfqq = crq->cfq_queue;
- struct cfq_data *cfqd = cfqq->cfqd;
- const int sync = cfq_crq_is_sync(crq);
- BUG_ON(!cfqq->queued[sync]);
- cfqq->queued[sync]--;
+ if (ON_RB(&crq->rb_node)) {
+ struct cfq_data *cfqd = cfqq->cfqd;
+ const int sync = cfq_crq_is_sync(crq);
- cfq_update_next_crq(crq);
+ BUG_ON(!cfqq->queued[sync]);
+ cfqq->queued[sync]--;
- rb_erase(&crq->rb_node, &cfqq->sort_list);
- RB_CLEAR_COLOR(&crq->rb_node);
+ cfq_update_next_crq(crq);
- if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
- cfq_del_cfqq_rr(cfqd, cfqq);
+ rb_erase(&crq->rb_node, &cfqq->sort_list);
+ RB_CLEAR_COLOR(&crq->rb_node);
+
+ if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
+ cfq_del_cfqq_rr(cfqd, cfqq);
+ }
}
static struct cfq_rq *
@@ -596,12 +627,12 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
* if that happens, put the alias on the dispatch list
*/
while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
- cfq_dispatch_insert(cfqd->queue, __alias);
+ cfq_dispatch_sort(cfqd->queue, __alias);
rb_insert_color(&crq->rb_node, &cfqq->sort_list);
if (!cfq_cfqq_on_rr(cfqq))
- cfq_add_cfqq_rr(cfqd, cfqq);
+ cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq));
/*
* check if this request is a better next-serve candidate
@@ -612,8 +643,10 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
static inline void
cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
{
- rb_erase(&crq->rb_node, &cfqq->sort_list);
- cfqq->queued[cfq_crq_is_sync(crq)]--;
+ if (ON_RB(&crq->rb_node)) {
+ rb_erase(&crq->rb_node, &cfqq->sort_list);
+ cfqq->queued[cfq_crq_is_sync(crq)]--;
+ }
cfq_add_crq_rb(crq);
}
@@ -643,28 +676,49 @@ static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
return NULL;
}
-static void cfq_activate_request(request_queue_t *q, struct request *rq)
+static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct cfq_rq *crq = RQ_DATA(rq);
- cfqd->rq_in_driver++;
+ if (crq) {
+ struct cfq_queue *cfqq = crq->cfq_queue;
+
+ if (cfq_crq_in_driver(crq)) {
+ cfq_clear_crq_in_driver(crq);
+ WARN_ON(!cfqd->rq_in_driver);
+ cfqd->rq_in_driver--;
+ }
+ if (cfq_crq_in_flight(crq)) {
+ const int sync = cfq_crq_is_sync(crq);
+
+ cfq_clear_crq_in_flight(crq);
+ WARN_ON(!cfqq->on_dispatch[sync]);
+ cfqq->on_dispatch[sync]--;
+ }
+ cfq_mark_crq_requeued(crq);
+ }
}
-static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
+/*
+ * make sure the service time gets corrected on reissue of this request
+ */
+static void cfq_requeue_request(request_queue_t *q, struct request *rq)
{
- struct cfq_data *cfqd = q->elevator->elevator_data;
-
- WARN_ON(!cfqd->rq_in_driver);
- cfqd->rq_in_driver--;
+ cfq_deactivate_request(q, rq);
+ list_add(&rq->queuelist, &q->queue_head);
}
-static void cfq_remove_request(struct request *rq)
+static void cfq_remove_request(request_queue_t *q, struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
- list_del_init(&rq->queuelist);
- cfq_del_crq_rb(crq);
- cfq_del_crq_hash(crq);
+ if (crq) {
+ list_del_init(&rq->queuelist);
+ cfq_del_crq_rb(crq);
+ cfq_remove_merge_hints(q, crq);
+
+ }
}
static int
@@ -674,6 +728,12 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
struct request *__rq;
int ret;
+ ret = elv_try_last_merge(q, bio);
+ if (ret != ELEVATOR_NO_MERGE) {
+ __rq = q->last_merge;
+ goto out_insert;
+ }
+
__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
if (__rq && elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_BACK_MERGE;
@@ -688,6 +748,8 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
+ q->last_merge = __rq;
+out_insert:
*req = __rq;
return ret;
}
@@ -700,12 +762,14 @@ static void cfq_merged_request(request_queue_t *q, struct request *req)
cfq_del_crq_hash(crq);
cfq_add_crq_hash(cfqd, crq);
- if (rq_rb_key(req) != crq->rb_key) {
+ if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) {
struct cfq_queue *cfqq = crq->cfq_queue;
cfq_update_next_crq(crq);
cfq_reposition_crq_rb(cfqq, crq);
}
+
+ q->last_merge = req;
}
static void
@@ -721,7 +785,7 @@ cfq_merged_requests(request_queue_t *q, struct request *rq,
time_before(next->start_time, rq->start_time))
list_move(&rq->queuelist, &next->queuelist);
- cfq_remove_request(next);
+ cfq_remove_request(q, next);
}
static inline void
@@ -928,15 +992,53 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
return 1;
}
-static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
+/*
+ * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues,
+ * this function sector sorts the selected request to minimize seeks. we start
+ * at cfqd->last_sector, not 0.
+ */
+static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_queue *cfqq = crq->cfq_queue;
+ struct list_head *head = &q->queue_head, *entry = head;
+ struct request *__rq;
+ sector_t last;
+
+ list_del(&crq->request->queuelist);
+
+ last = cfqd->last_sector;
+ list_for_each_entry_reverse(__rq, head, queuelist) {
+ struct cfq_rq *__crq = RQ_DATA(__rq);
+
+ if (blk_barrier_rq(__rq))
+ break;
+ if (!blk_fs_request(__rq))
+ break;
+ if (cfq_crq_requeued(__crq))
+ break;
+
+ if (__rq->sector <= crq->request->sector)
+ break;
+ if (__rq->sector > last && crq->request->sector < last) {
+ last = crq->request->sector + crq->request->nr_sectors;
+ break;
+ }
+ entry = &__rq->queuelist;
+ }
+
+ cfqd->last_sector = last;
cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
- cfq_remove_request(crq->request);
+
+ cfq_del_crq_rb(crq);
+ cfq_remove_merge_hints(q, crq);
+
+ cfq_mark_crq_in_flight(crq);
+ cfq_clear_crq_requeued(crq);
+
cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
- elv_dispatch_sort(q, crq->request);
+ list_add_tail(&crq->request->queuelist, entry);
}
/*
@@ -1057,7 +1159,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
/*
* finally, insert request into driver dispatch list
*/
- cfq_dispatch_insert(cfqd->queue, crq);
+ cfq_dispatch_sort(cfqd->queue, crq);
cfqd->dispatch_slice++;
dispatched++;
@@ -1092,7 +1194,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
static int
-cfq_dispatch_requests(request_queue_t *q, int force)
+cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_queue *cfqq;
@@ -1102,25 +1204,12 @@ cfq_dispatch_requests(request_queue_t *q, int force)
cfqq = cfq_select_queue(cfqd, force);
if (cfqq) {
- int max_dispatch;
-
- /*
- * if idle window is disabled, allow queue buildup
- */
- if (!cfq_cfqq_idle_window(cfqq) &&
- cfqd->rq_in_driver >= cfqd->cfq_max_depth)
- return 0;
-
cfq_clear_cfqq_must_dispatch(cfqq);
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);
- if (!force) {
- max_dispatch = cfqd->cfq_quantum;
- if (cfq_class_idle(cfqq))
- max_dispatch = 1;
- } else
- max_dispatch = INT_MAX;
+ if (cfq_class_idle(cfqq))
+ max_dispatch = 1;
return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
}
@@ -1128,6 +1217,93 @@ cfq_dispatch_requests(request_queue_t *q, int force)
return 0;
}
+static inline void cfq_account_dispatch(struct cfq_rq *crq)
+{
+ struct cfq_queue *cfqq = crq->cfq_queue;
+ struct cfq_data *cfqd = cfqq->cfqd;
+
+ if (unlikely(!blk_fs_request(crq->request)))
+ return;
+
+ /*
+ * accounted bit is necessary since some drivers will call
+ * elv_next_request() many times for the same request (eg ide)
+ */
+ if (cfq_crq_in_driver(crq))
+ return;
+
+ cfq_mark_crq_in_driver(crq);
+ cfqd->rq_in_driver++;
+}
+
+static inline void
+cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
+{
+ struct cfq_data *cfqd = cfqq->cfqd;
+ unsigned long now;
+
+ if (!cfq_crq_in_driver(crq))
+ return;
+
+ now = jiffies;
+
+ WARN_ON(!cfqd->rq_in_driver);
+ cfqd->rq_in_driver--;
+
+ if (!cfq_class_idle(cfqq))
+ cfqd->last_end_request = now;
+
+ if (!cfq_cfqq_dispatched(cfqq)) {
+ if (cfq_cfqq_on_rr(cfqq)) {
+ cfqq->service_last = now;
+ cfq_resort_rr_list(cfqq, 0);
+ }
+ if (cfq_cfqq_expired(cfqq)) {
+ __cfq_slice_expired(cfqd, cfqq, 0);
+ cfq_schedule_dispatch(cfqd);
+ }
+ }
+
+ if (cfq_crq_is_sync(crq))
+ crq->io_context->last_end_request = now;
+}
+
+static struct request *cfq_next_request(request_queue_t *q)
+{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct request *rq;
+
+ if (!list_empty(&q->queue_head)) {
+ struct cfq_rq *crq;
+dispatch:
+ rq = list_entry_rq(q->queue_head.next);
+
+ crq = RQ_DATA(rq);
+ if (crq) {
+ struct cfq_queue *cfqq = crq->cfq_queue;
+
+ /*
+ * if idle window is disabled, allow queue buildup
+ */
+ if (!cfq_crq_in_driver(crq) &&
+ !cfq_cfqq_idle_window(cfqq) &&
+ !blk_barrier_rq(rq) &&
+ cfqd->rq_in_driver >= cfqd->cfq_max_depth)
+ return NULL;
+
+ cfq_remove_merge_hints(q, crq);
+ cfq_account_dispatch(crq);
+ }
+
+ return rq;
+ }
+
+ if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0))
+ goto dispatch;
+
+ return NULL;
+}
+
/*
* task holds one reference to the queue, dropped when task exits. each crq
* in-flight on this queue also holds a reference, dropped when crq is freed.
@@ -1246,7 +1422,7 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
}
static struct cfq_io_context *
-cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
+cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
{
struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
@@ -1341,7 +1517,7 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
static struct cfq_queue *
cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
- gfp_t gfp_mask)
+ int gfp_mask)
{
const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
struct cfq_queue *cfqq, *new_cfqq = NULL;
@@ -1402,7 +1578,7 @@ cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
* cfqq, so we don't need to worry about it disappearing
*/
static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
{
struct io_context *ioc = NULL;
struct cfq_io_context *cic;
@@ -1640,9 +1816,8 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
}
-static void cfq_insert_request(request_queue_t *q, struct request *rq)
+static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
{
- struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_rq *crq = RQ_DATA(rq);
struct cfq_queue *cfqq = crq->cfq_queue;
@@ -1652,43 +1827,66 @@ static void cfq_insert_request(request_queue_t *q, struct request *rq)
list_add_tail(&rq->queuelist, &cfqq->fifo);
- if (rq_mergeable(rq))
+ if (rq_mergeable(rq)) {
cfq_add_crq_hash(cfqd, crq);
+ if (!cfqd->queue->last_merge)
+ cfqd->queue->last_merge = rq;
+ }
+
cfq_crq_enqueued(cfqd, cfqq, crq);
}
+static void
+cfq_insert_request(request_queue_t *q, struct request *rq, int where)
+{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+
+ switch (where) {
+ case ELEVATOR_INSERT_BACK:
+ while (cfq_dispatch_requests(q, INT_MAX, 1))
+ ;
+ list_add_tail(&rq->queuelist, &q->queue_head);
+ /*
+ * If we were idling with pending requests on
+ * inactive cfqqs, force dispatching will
+ * remove the idle timer and the queue won't
+ * be kicked by __make_request() afterward.
+ * Kick it here.
+ */
+ cfq_schedule_dispatch(cfqd);
+ break;
+ case ELEVATOR_INSERT_FRONT:
+ list_add(&rq->queuelist, &q->queue_head);
+ break;
+ case ELEVATOR_INSERT_SORT:
+ BUG_ON(!blk_fs_request(rq));
+ cfq_enqueue(cfqd, rq);
+ break;
+ default:
+ printk("%s: bad insert point %d\n", __FUNCTION__,where);
+ return;
+ }
+}
+
static void cfq_completed_request(request_queue_t *q, struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
- struct cfq_queue *cfqq = crq->cfq_queue;
- struct cfq_data *cfqd = cfqq->cfqd;
- const int sync = cfq_crq_is_sync(crq);
- unsigned long now;
+ struct cfq_queue *cfqq;
- now = jiffies;
+ if (unlikely(!blk_fs_request(rq)))
+ return;
- WARN_ON(!cfqd->rq_in_driver);
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqd->rq_in_driver--;
- cfqq->on_dispatch[sync]--;
+ cfqq = crq->cfq_queue;
- if (!cfq_class_idle(cfqq))
- cfqd->last_end_request = now;
+ if (cfq_crq_in_flight(crq)) {
+ const int sync = cfq_crq_is_sync(crq);
- if (!cfq_cfqq_dispatched(cfqq)) {
- if (cfq_cfqq_on_rr(cfqq)) {
- cfqq->service_last = now;
- cfq_resort_rr_list(cfqq, 0);
- }
- if (cfq_cfqq_expired(cfqq)) {
- __cfq_slice_expired(cfqd, cfqq, 0);
- cfq_schedule_dispatch(cfqd);
- }
+ WARN_ON(!cfqq->on_dispatch[sync]);
+ cfqq->on_dispatch[sync]--;
}
- if (cfq_crq_is_sync(crq))
- crq->io_context->last_end_request = now;
+ cfq_account_completion(cfqq, crq);
}
static struct request *
@@ -1877,7 +2075,7 @@ static void cfq_put_request(request_queue_t *q, struct request *rq)
*/
static int
cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- gfp_t gfp_mask)
+ int gfp_mask)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
@@ -1920,6 +2118,9 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
INIT_HLIST_NODE(&crq->hash);
crq->cfq_queue = cfqq;
crq->io_context = cic;
+ cfq_clear_crq_in_flight(crq);
+ cfq_clear_crq_in_driver(crq);
+ cfq_clear_crq_requeued(crq);
if (rw == READ || process_sync(tsk))
cfq_mark_crq_is_sync(crq);
@@ -2000,7 +2201,7 @@ static void cfq_idle_slice_timer(unsigned long data)
* only expire and reinvoke request handler, if there are
* other queues with pending requests
*/
- if (!cfqd->busy_queues) {
+ if (!cfq_pending_requests(cfqd)) {
cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
add_timer(&cfqd->idle_slice_timer);
goto out_cont;
@@ -2375,9 +2576,10 @@ static struct elevator_type iosched_cfq = {
.elevator_merge_fn = cfq_merge,
.elevator_merged_fn = cfq_merged_request,
.elevator_merge_req_fn = cfq_merged_requests,
- .elevator_dispatch_fn = cfq_dispatch_requests,
+ .elevator_next_req_fn = cfq_next_request,
.elevator_add_req_fn = cfq_insert_request,
- .elevator_activate_req_fn = cfq_activate_request,
+ .elevator_remove_req_fn = cfq_remove_request,
+ .elevator_requeue_req_fn = cfq_requeue_request,
.elevator_deactivate_req_fn = cfq_deactivate_request,
.elevator_queue_empty_fn = cfq_queue_empty,
.elevator_completed_req_fn = cfq_completed_request,
diff --git a/trunk/drivers/block/deadline-iosched.c b/trunk/drivers/block/deadline-iosched.c
index 7929471d7df7..52a3ae5289a0 100644
--- a/trunk/drivers/block/deadline-iosched.c
+++ b/trunk/drivers/block/deadline-iosched.c
@@ -50,6 +50,7 @@ struct deadline_data {
* next in sort order. read, write or both are NULL
*/
struct deadline_rq *next_drq[2];
+ struct list_head *dispatch; /* driver dispatch queue */
struct list_head *hash; /* request hash */
unsigned int batching; /* number of sequential requests made */
sector_t last_sector; /* head position */
@@ -112,6 +113,15 @@ static inline void deadline_del_drq_hash(struct deadline_rq *drq)
__deadline_del_drq_hash(drq);
}
+static void
+deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq)
+{
+ deadline_del_drq_hash(drq);
+
+ if (q->last_merge == drq->request)
+ q->last_merge = NULL;
+}
+
static inline void
deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
{
@@ -229,9 +239,10 @@ deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
dd->next_drq[data_dir] = rb_entry_drq(rbnext);
}
- BUG_ON(!ON_RB(&drq->rb_node));
- rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
- RB_CLEAR(&drq->rb_node);
+ if (ON_RB(&drq->rb_node)) {
+ rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
+ RB_CLEAR(&drq->rb_node);
+ }
}
static struct request *
@@ -275,7 +286,7 @@ deadline_find_first_drq(struct deadline_data *dd, int data_dir)
/*
* add drq to rbtree and fifo
*/
-static void
+static inline void
deadline_add_request(struct request_queue *q, struct request *rq)
{
struct deadline_data *dd = q->elevator->elevator_data;
@@ -290,8 +301,12 @@ deadline_add_request(struct request_queue *q, struct request *rq)
drq->expires = jiffies + dd->fifo_expire[data_dir];
list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
- if (rq_mergeable(rq))
+ if (rq_mergeable(rq)) {
deadline_add_drq_hash(dd, drq);
+
+ if (!q->last_merge)
+ q->last_merge = rq;
+ }
}
/*
@@ -300,11 +315,14 @@ deadline_add_request(struct request_queue *q, struct request *rq)
static void deadline_remove_request(request_queue_t *q, struct request *rq)
{
struct deadline_rq *drq = RQ_DATA(rq);
- struct deadline_data *dd = q->elevator->elevator_data;
- list_del_init(&drq->fifo);
- deadline_del_drq_rb(dd, drq);
- deadline_del_drq_hash(drq);
+ if (drq) {
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ list_del_init(&drq->fifo);
+ deadline_remove_merge_hints(q, drq);
+ deadline_del_drq_rb(dd, drq);
+ }
}
static int
@@ -314,6 +332,15 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
struct request *__rq;
int ret;
+ /*
+ * try last_merge to avoid going to hash
+ */
+ ret = elv_try_last_merge(q, bio);
+ if (ret != ELEVATOR_NO_MERGE) {
+ __rq = q->last_merge;
+ goto out_insert;
+ }
+
/*
* see if the merge hash can satisfy a back merge
*/
@@ -346,6 +373,8 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
+ q->last_merge = __rq;
+out_insert:
if (ret)
deadline_hot_drq_hash(dd, RQ_DATA(__rq));
*req = __rq;
@@ -370,6 +399,8 @@ static void deadline_merged_request(request_queue_t *q, struct request *req)
deadline_del_drq_rb(dd, drq);
deadline_add_drq_rb(dd, drq);
}
+
+ q->last_merge = req;
}
static void
@@ -421,7 +452,7 @@ deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
request_queue_t *q = drq->request->q;
deadline_remove_request(q, drq->request);
- elv_dispatch_add_tail(q, drq->request);
+ list_add_tail(&drq->request->queuelist, dd->dispatch);
}
/*
@@ -471,9 +502,8 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)
* deadline_dispatch_requests selects the best request according to
* read/write expire, fifo_batch, etc
*/
-static int deadline_dispatch_requests(request_queue_t *q, int force)
+static int deadline_dispatch_requests(struct deadline_data *dd)
{
- struct deadline_data *dd = q->elevator->elevator_data;
const int reads = !list_empty(&dd->fifo_list[READ]);
const int writes = !list_empty(&dd->fifo_list[WRITE]);
struct deadline_rq *drq;
@@ -567,12 +597,65 @@ static int deadline_dispatch_requests(request_queue_t *q, int force)
return 1;
}
+static struct request *deadline_next_request(request_queue_t *q)
+{
+ struct deadline_data *dd = q->elevator->elevator_data;
+ struct request *rq;
+
+ /*
+ * if there are still requests on the dispatch queue, grab the first one
+ */
+ if (!list_empty(dd->dispatch)) {
+dispatch:
+ rq = list_entry_rq(dd->dispatch->next);
+ return rq;
+ }
+
+ if (deadline_dispatch_requests(dd))
+ goto dispatch;
+
+ return NULL;
+}
+
+static void
+deadline_insert_request(request_queue_t *q, struct request *rq, int where)
+{
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ /* barriers must flush the reorder queue */
+ if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
+ && where == ELEVATOR_INSERT_SORT))
+ where = ELEVATOR_INSERT_BACK;
+
+ switch (where) {
+ case ELEVATOR_INSERT_BACK:
+ while (deadline_dispatch_requests(dd))
+ ;
+ list_add_tail(&rq->queuelist, dd->dispatch);
+ break;
+ case ELEVATOR_INSERT_FRONT:
+ list_add(&rq->queuelist, dd->dispatch);
+ break;
+ case ELEVATOR_INSERT_SORT:
+ BUG_ON(!blk_fs_request(rq));
+ deadline_add_request(q, rq);
+ break;
+ default:
+ printk("%s: bad insert point %d\n", __FUNCTION__,where);
+ return;
+ }
+}
+
static int deadline_queue_empty(request_queue_t *q)
{
struct deadline_data *dd = q->elevator->elevator_data;
- return list_empty(&dd->fifo_list[WRITE])
- && list_empty(&dd->fifo_list[READ]);
+ if (!list_empty(&dd->fifo_list[WRITE])
+ || !list_empty(&dd->fifo_list[READ])
+ || !list_empty(dd->dispatch))
+ return 0;
+
+ return 1;
}
static struct request *
@@ -650,6 +733,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
dd->sort_list[READ] = RB_ROOT;
dd->sort_list[WRITE] = RB_ROOT;
+ dd->dispatch = &q->queue_head;
dd->fifo_expire[READ] = read_expire;
dd->fifo_expire[WRITE] = write_expire;
dd->writes_starved = writes_starved;
@@ -664,13 +748,15 @@ static void deadline_put_request(request_queue_t *q, struct request *rq)
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(rq);
- mempool_free(drq, dd->drq_pool);
- rq->elevator_private = NULL;
+ if (drq) {
+ mempool_free(drq, dd->drq_pool);
+ rq->elevator_private = NULL;
+ }
}
static int
deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- gfp_t gfp_mask)
+ int gfp_mask)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq;
@@ -831,8 +917,9 @@ static struct elevator_type iosched_deadline = {
.elevator_merge_fn = deadline_merge,
.elevator_merged_fn = deadline_merged_request,
.elevator_merge_req_fn = deadline_merged_requests,
- .elevator_dispatch_fn = deadline_dispatch_requests,
- .elevator_add_req_fn = deadline_add_request,
+ .elevator_next_req_fn = deadline_next_request,
+ .elevator_add_req_fn = deadline_insert_request,
+ .elevator_remove_req_fn = deadline_remove_request,
.elevator_queue_empty_fn = deadline_queue_empty,
.elevator_former_req_fn = deadline_former_request,
.elevator_latter_req_fn = deadline_latter_request,
diff --git a/trunk/drivers/block/elevator.c b/trunk/drivers/block/elevator.c
index 55621d5c5774..98f0126a2deb 100644
--- a/trunk/drivers/block/elevator.c
+++ b/trunk/drivers/block/elevator.c
@@ -34,7 +34,6 @@
#include
#include
#include
-#include
#include
@@ -84,11 +83,21 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio)
}
EXPORT_SYMBOL(elv_try_merge);
+inline int elv_try_last_merge(request_queue_t *q, struct bio *bio)
+{
+ if (q->last_merge)
+ return elv_try_merge(q->last_merge, bio);
+
+ return ELEVATOR_NO_MERGE;
+}
+EXPORT_SYMBOL(elv_try_last_merge);
+
static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e = NULL;
struct list_head *entry;
+ spin_lock_irq(&elv_list_lock);
list_for_each(entry, &elv_list) {
struct elevator_type *__e;
@@ -99,6 +108,7 @@ static struct elevator_type *elevator_find(const char *name)
break;
}
}
+ spin_unlock_irq(&elv_list_lock);
return e;
}
@@ -110,15 +120,12 @@ static void elevator_put(struct elevator_type *e)
static struct elevator_type *elevator_get(const char *name)
{
- struct elevator_type *e;
+ struct elevator_type *e = elevator_find(name);
- spin_lock_irq(&elv_list_lock);
-
- e = elevator_find(name);
- if (e && !try_module_get(e->elevator_owner))
- e = NULL;
-
- spin_unlock_irq(&elv_list_lock);
+ if (!e)
+ return NULL;
+ if (!try_module_get(e->elevator_owner))
+ return NULL;
return e;
}
@@ -132,6 +139,8 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e,
eq->ops = &e->ops;
eq->elevator_type = e;
+ INIT_LIST_HEAD(&q->queue_head);
+ q->last_merge = NULL;
q->elevator = eq;
if (eq->ops->elevator_init_fn)
@@ -144,15 +153,11 @@ static char chosen_elevator[16];
static void elevator_setup_default(void)
{
- struct elevator_type *e;
-
/*
* check if default is set and exists
*/
- if (chosen_elevator[0] && (e = elevator_get(chosen_elevator))) {
- elevator_put(e);
+ if (chosen_elevator[0] && elevator_find(chosen_elevator))
return;
- }
#if defined(CONFIG_IOSCHED_AS)
strcpy(chosen_elevator, "anticipatory");
@@ -181,11 +186,6 @@ int elevator_init(request_queue_t *q, char *name)
struct elevator_queue *eq;
int ret = 0;
- INIT_LIST_HEAD(&q->queue_head);
- q->last_merge = NULL;
- q->end_sector = 0;
- q->boundary_rq = NULL;
-
elevator_setup_default();
if (!name)
@@ -220,52 +220,9 @@ void elevator_exit(elevator_t *e)
kfree(e);
}
-/*
- * Insert rq into dispatch queue of q. Queue lock must be held on
- * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be
- * appended to the dispatch queue. To be used by specific elevators.
- */
-void elv_dispatch_sort(request_queue_t *q, struct request *rq)
-{
- sector_t boundary;
- struct list_head *entry;
-
- if (q->last_merge == rq)
- q->last_merge = NULL;
-
- boundary = q->end_sector;
-
- list_for_each_prev(entry, &q->queue_head) {
- struct request *pos = list_entry_rq(entry);
-
- if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
- break;
- if (rq->sector >= boundary) {
- if (pos->sector < boundary)
- continue;
- } else {
- if (pos->sector >= boundary)
- break;
- }
- if (rq->sector >= pos->sector)
- break;
- }
-
- list_add(&rq->queuelist, entry);
-}
-
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
- int ret;
-
- if (q->last_merge) {
- ret = elv_try_merge(q->last_merge, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- *req = q->last_merge;
- return ret;
- }
- }
if (e->ops->elevator_merge_fn)
return e->ops->elevator_merge_fn(q, req, bio);
@@ -279,8 +236,6 @@ void elv_merged_request(request_queue_t *q, struct request *rq)
if (e->ops->elevator_merged_fn)
e->ops->elevator_merged_fn(q, rq);
-
- q->last_merge = rq;
}
void elv_merge_requests(request_queue_t *q, struct request *rq,
@@ -288,13 +243,20 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
{
elevator_t *e = q->elevator;
+ if (q->last_merge == next)
+ q->last_merge = NULL;
+
if (e->ops->elevator_merge_req_fn)
e->ops->elevator_merge_req_fn(q, rq, next);
-
- q->last_merge = rq;
}
-void elv_requeue_request(request_queue_t *q, struct request *rq)
+/*
+ * For careful internal use by the block layer. Essentially the same as
+ * a requeue in that it tells the io scheduler that this request is not
+ * active in the driver or hardware anymore, but we don't want the request
+ * added back to the scheduler. Function is not exported.
+ */
+void elv_deactivate_request(request_queue_t *q, struct request *rq)
{
elevator_t *e = q->elevator;
@@ -302,14 +264,19 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
* it already went through dequeue, we need to decrement the
* in_flight count again
*/
- if (blk_account_rq(rq)) {
+ if (blk_account_rq(rq))
q->in_flight--;
- if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn)
- e->ops->elevator_deactivate_req_fn(q, rq);
- }
rq->flags &= ~REQ_STARTED;
+ if (e->ops->elevator_deactivate_req_fn)
+ e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
+void elv_requeue_request(request_queue_t *q, struct request *rq)
+{
+ elv_deactivate_request(q, rq);
+
/*
* if this is the flush, requeue the original instead and drop the flush
*/
@@ -318,27 +285,31 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
rq = rq->end_io_data;
}
- __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+ /*
+ * the request is prepped and may have some resources allocated.
+ * allowing unprepped requests to pass this one may cause resource
+ * deadlock. turn on softbarrier.
+ */
+ rq->flags |= REQ_SOFTBARRIER;
+
+ /*
+ * if iosched has an explicit requeue hook, then use that. otherwise
+ * just put the request at the front of the queue
+ */
+ if (q->elevator->ops->elevator_requeue_req_fn)
+ q->elevator->ops->elevator_requeue_req_fn(q, rq);
+ else
+ __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
}
void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug)
{
- if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
- /*
- * barriers implicitly indicate back insertion
- */
- if (where == ELEVATOR_INSERT_SORT)
- where = ELEVATOR_INSERT_BACK;
-
- /*
- * this request is scheduling boundary, update end_sector
- */
- if (blk_fs_request(rq)) {
- q->end_sector = rq_end_sector(rq);
- q->boundary_rq = rq;
- }
- } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
+ /*
+ * barriers implicitly indicate back insertion
+ */
+ if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) &&
+ where == ELEVATOR_INSERT_SORT)
where = ELEVATOR_INSERT_BACK;
if (plug)
@@ -346,54 +317,23 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
rq->q = q;
- switch (where) {
- case ELEVATOR_INSERT_FRONT:
- rq->flags |= REQ_SOFTBARRIER;
+ if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
+ q->elevator->ops->elevator_add_req_fn(q, rq, where);
- list_add(&rq->queuelist, &q->queue_head);
- break;
+ if (blk_queue_plugged(q)) {
+ int nrq = q->rq.count[READ] + q->rq.count[WRITE]
+ - q->in_flight;
- case ELEVATOR_INSERT_BACK:
- rq->flags |= REQ_SOFTBARRIER;
-
- while (q->elevator->ops->elevator_dispatch_fn(q, 1))
- ;
- list_add_tail(&rq->queuelist, &q->queue_head);
+ if (nrq >= q->unplug_thresh)
+ __generic_unplug_device(q);
+ }
+ } else
/*
- * We kick the queue here for the following reasons.
- * - The elevator might have returned NULL previously
- * to delay requests and returned them now. As the
- * queue wasn't empty before this request, ll_rw_blk
- * won't run the queue on return, resulting in hang.
- * - Usually, back inserted requests won't be merged
- * with anything. There's no point in delaying queue
- * processing.
+ * if drain is set, store the request "locally". when the drain
+ * is finished, the requests will be handed ordered to the io
+ * scheduler
*/
- blk_remove_plug(q);
- q->request_fn(q);
- break;
-
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- rq->flags |= REQ_SORTED;
- q->elevator->ops->elevator_add_req_fn(q, rq);
- if (q->last_merge == NULL && rq_mergeable(rq))
- q->last_merge = rq;
- break;
-
- default:
- printk(KERN_ERR "%s: bad insertion point %d\n",
- __FUNCTION__, where);
- BUG();
- }
-
- if (blk_queue_plugged(q)) {
- int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- - q->in_flight;
-
- if (nrq >= q->unplug_thresh)
- __generic_unplug_device(q);
- }
+ list_add_tail(&rq->queuelist, &q->drain_list);
}
void elv_add_request(request_queue_t *q, struct request *rq, int where,
@@ -408,19 +348,13 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
static inline struct request *__elv_next_request(request_queue_t *q)
{
- struct request *rq;
-
- if (unlikely(list_empty(&q->queue_head) &&
- !q->elevator->ops->elevator_dispatch_fn(q, 0)))
- return NULL;
-
- rq = list_entry_rq(q->queue_head.next);
+ struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
/*
* if this is a barrier write and the device has to issue a
* flush sequence to support it, check how far we are
*/
- if (blk_fs_request(rq) && blk_barrier_rq(rq)) {
+ if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
if (q->ordered == QUEUE_ORDERED_FLUSH &&
@@ -437,30 +371,15 @@ struct request *elv_next_request(request_queue_t *q)
int ret;
while ((rq = __elv_next_request(q)) != NULL) {
- if (!(rq->flags & REQ_STARTED)) {
- elevator_t *e = q->elevator;
-
- /*
- * This is the first time the device driver
- * sees this request (possibly after
- * requeueing). Notify IO scheduler.
- */
- if (blk_sorted_rq(rq) &&
- e->ops->elevator_activate_req_fn)
- e->ops->elevator_activate_req_fn(q, rq);
-
- /*
- * just mark as started even if we don't start
- * it, a request that has been delayed should
- * not be passed by new incoming requests
- */
- rq->flags |= REQ_STARTED;
- }
+ /*
+ * just mark as started even if we don't start it, a request
+ * that has been delayed should not be passed by new incoming
+ * requests
+ */
+ rq->flags |= REQ_STARTED;
- if (!q->boundary_rq || q->boundary_rq == rq) {
- q->end_sector = rq_end_sector(rq);
- q->boundary_rq = NULL;
- }
+ if (rq == q->last_merge)
+ q->last_merge = NULL;
if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
break;
@@ -472,9 +391,9 @@ struct request *elv_next_request(request_queue_t *q)
/*
* the request may have been (partially) prepped.
* we need to keep this request in the front to
- * avoid resource deadlock. REQ_STARTED will
- * prevent other fs requests from passing this one.
+ * avoid resource deadlock. turn on softbarrier.
*/
+ rq->flags |= REQ_SOFTBARRIER;
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {
@@ -497,32 +416,42 @@ struct request *elv_next_request(request_queue_t *q)
return rq;
}
-void elv_dequeue_request(request_queue_t *q, struct request *rq)
+void elv_remove_request(request_queue_t *q, struct request *rq)
{
- BUG_ON(list_empty(&rq->queuelist));
-
- list_del_init(&rq->queuelist);
+ elevator_t *e = q->elevator;
/*
* the time frame between a request being removed from the lists
* and to it is freed is accounted as io that is in progress at
- * the driver side.
+ * the driver side. note that we only account requests that the
+ * driver has seen (REQ_STARTED set), to avoid false accounting
+ * for request-request merges
*/
if (blk_account_rq(rq))
q->in_flight++;
+
+ /*
+ * the main clearing point for q->last_merge is on retrieval of
+ * request by driver (it calls elv_next_request()), but it _can_
+ * also happen here if a request is added to the queue but later
+ * deleted without ever being given to driver (merged with another
+ * request).
+ */
+ if (rq == q->last_merge)
+ q->last_merge = NULL;
+
+ if (e->ops->elevator_remove_req_fn)
+ e->ops->elevator_remove_req_fn(q, rq);
}
int elv_queue_empty(request_queue_t *q)
{
elevator_t *e = q->elevator;
- if (!list_empty(&q->queue_head))
- return 0;
-
if (e->ops->elevator_queue_empty_fn)
return e->ops->elevator_queue_empty_fn(q);
- return 1;
+ return list_empty(&q->queue_head);
}
struct request *elv_latter_request(request_queue_t *q, struct request *rq)
@@ -558,7 +487,7 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
}
int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- gfp_t gfp_mask)
+ int gfp_mask)
{
elevator_t *e = q->elevator;
@@ -594,11 +523,11 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
/*
* request is released from the driver, io must be done
*/
- if (blk_account_rq(rq)) {
+ if (blk_account_rq(rq))
q->in_flight--;
- if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
- e->ops->elevator_completed_req_fn(q, rq);
- }
+
+ if (e->ops->elevator_completed_req_fn)
+ e->ops->elevator_completed_req_fn(q, rq);
}
int elv_register_queue(struct request_queue *q)
@@ -626,9 +555,10 @@ void elv_unregister_queue(struct request_queue *q)
int elv_register(struct elevator_type *e)
{
- spin_lock_irq(&elv_list_lock);
if (elevator_find(e->elevator_name))
BUG();
+
+ spin_lock_irq(&elv_list_lock);
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);
@@ -652,36 +582,25 @@ EXPORT_SYMBOL_GPL(elv_unregister);
* switch to new_e io scheduler. be careful not to introduce deadlocks -
* we don't free the old io scheduler, before we have allocated what we
* need for the new one. this way we have a chance of going back to the old
- * one, if the new one fails init for some reason.
+ * one, if the new one fails init for some reason. we also do an intermediate
+ * switch to noop to ensure safety with stack-allocated requests, since they
+ * don't originate from the block layer allocator. noop is safe here, because
+ * it never needs to touch the elevator itself for completion events. DRAIN
+ * flags will make sure we don't touch it for additions either.
*/
static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
{
- elevator_t *old_elevator, *e;
+ elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
+ struct elevator_type *noop_elevator = NULL;
+ elevator_t *old_elevator;
- /*
- * Allocate new elevator
- */
- e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
if (!e)
goto error;
/*
- * Turn on BYPASS and drain all requests w/ elevator private data
+ * first step, drain requests from the block freelist
*/
- spin_lock_irq(q->queue_lock);
-
- set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-
- while (q->elevator->ops->elevator_dispatch_fn(q, 1))
- ;
-
- while (q->rq.elvpriv) {
- spin_unlock_irq(q->queue_lock);
- msleep(10);
- spin_lock_irq(q->queue_lock);
- }
-
- spin_unlock_irq(q->queue_lock);
+ blk_wait_queue_drained(q, 0);
/*
* unregister old elevator data
@@ -689,6 +608,18 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
elv_unregister_queue(q);
old_elevator = q->elevator;
+ /*
+ * next step, switch to noop since it uses no private rq structures
+ * and doesn't allocate any memory for anything. then wait for any
+ * non-fs requests in-flight
+ */
+ noop_elevator = elevator_get("noop");
+ spin_lock_irq(q->queue_lock);
+ elevator_attach(q, noop_elevator, e);
+ spin_unlock_irq(q->queue_lock);
+
+ blk_wait_queue_drained(q, 1);
+
/*
* attach and start new elevator
*/
@@ -699,10 +630,11 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
goto fail_register;
/*
- * finally exit old elevator and turn off BYPASS.
+ * finally exit old elevator and start queue again
*/
elevator_exit(old_elevator);
- clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+ blk_finish_queue_drain(q);
+ elevator_put(noop_elevator);
return;
fail_register:
@@ -711,13 +643,13 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
* one again (along with re-adding the sysfs dir)
*/
elevator_exit(e);
- e = NULL;
fail:
q->elevator = old_elevator;
elv_register_queue(q);
- clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
- kfree(e);
+ blk_finish_queue_drain(q);
error:
+ if (noop_elevator)
+ elevator_put(noop_elevator);
elevator_put(new_e);
printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
}
@@ -769,12 +701,11 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
return len;
}
-EXPORT_SYMBOL(elv_dispatch_sort);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_requeue_request);
EXPORT_SYMBOL(elv_next_request);
-EXPORT_SYMBOL(elv_dequeue_request);
+EXPORT_SYMBOL(elv_remove_request);
EXPORT_SYMBOL(elv_queue_empty);
EXPORT_SYMBOL(elv_completed_request);
EXPORT_SYMBOL(elevator_exit);
diff --git a/trunk/drivers/block/ll_rw_blk.c b/trunk/drivers/block/ll_rw_blk.c
index 0af73512b9a8..baedac522945 100644
--- a/trunk/drivers/block/ll_rw_blk.c
+++ b/trunk/drivers/block/ll_rw_blk.c
@@ -263,6 +263,8 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
blk_queue_activity_fn(q, NULL, NULL);
+
+ INIT_LIST_HEAD(&q->drain_list);
}
EXPORT_SYMBOL(blk_queue_make_request);
@@ -351,8 +353,6 @@ static void blk_pre_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
- elv_completed_request(q, flush_rq);
-
rq->flags |= REQ_BAR_PREFLUSH;
if (!flush_rq->errors)
@@ -369,8 +369,6 @@ static void blk_post_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
- elv_completed_request(q, flush_rq);
-
rq->flags |= REQ_BAR_POSTFLUSH;
q->end_flush_fn(q, flush_rq);
@@ -410,6 +408,8 @@ struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
if (!list_empty(&rq->queuelist))
blkdev_dequeue_request(rq);
+ elv_deactivate_request(q, rq);
+
flush_rq->end_io_data = rq;
flush_rq->end_io = blk_pre_flush_end_io;
@@ -1040,7 +1040,6 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
static char *rq_flags[] = {
"REQ_RW",
"REQ_FAILFAST",
- "REQ_SORTED",
"REQ_SOFTBARRIER",
"REQ_HARDBARRIER",
"REQ_CMD",
@@ -1048,7 +1047,6 @@ static char *rq_flags[] = {
"REQ_STARTED",
"REQ_DONTPREP",
"REQ_QUEUED",
- "REQ_ELVPRIV",
"REQ_PC",
"REQ_BLOCK_PC",
"REQ_SENSE",
@@ -1639,9 +1637,9 @@ static int blk_init_free_list(request_queue_t *q)
rl->count[READ] = rl->count[WRITE] = 0;
rl->starved[READ] = rl->starved[WRITE] = 0;
- rl->elvpriv = 0;
init_waitqueue_head(&rl->wait[READ]);
init_waitqueue_head(&rl->wait[WRITE]);
+ init_waitqueue_head(&rl->drain);
rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
mempool_free_slab, request_cachep, q->node);
@@ -1654,13 +1652,13 @@ static int blk_init_free_list(request_queue_t *q)
static int __make_request(request_queue_t *, struct bio *);
-request_queue_t *blk_alloc_queue(gfp_t gfp_mask)
+request_queue_t *blk_alloc_queue(int gfp_mask)
{
return blk_alloc_queue_node(gfp_mask, -1);
}
EXPORT_SYMBOL(blk_alloc_queue);
-request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
+request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
{
request_queue_t *q;
@@ -1784,14 +1782,12 @@ EXPORT_SYMBOL(blk_get_queue);
static inline void blk_free_request(request_queue_t *q, struct request *rq)
{
- if (rq->flags & REQ_ELVPRIV)
- elv_put_request(q, rq);
+ elv_put_request(q, rq);
mempool_free(rq, q->rq.rq_pool);
}
static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
- int priv, gfp_t gfp_mask)
+blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
{
struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
@@ -1804,15 +1800,11 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
*/
rq->flags = rw;
- if (priv) {
- if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) {
- mempool_free(rq, q->rq.rq_pool);
- return NULL;
- }
- rq->flags |= REQ_ELVPRIV;
- }
+ if (!elv_set_request(q, rq, bio, gfp_mask))
+ return rq;
- return rq;
+ mempool_free(rq, q->rq.rq_pool);
+ return NULL;
}
/*
@@ -1868,18 +1860,22 @@ static void __freed_request(request_queue_t *q, int rw)
* A request has just been released. Account for it, update the full and
* congestion status, wake up any waiters. Called under q->queue_lock.
*/
-static void freed_request(request_queue_t *q, int rw, int priv)
+static void freed_request(request_queue_t *q, int rw)
{
struct request_list *rl = &q->rq;
rl->count[rw]--;
- if (priv)
- rl->elvpriv--;
__freed_request(q, rw);
if (unlikely(rl->starved[rw ^ 1]))
__freed_request(q, rw ^ 1);
+
+ if (!rl->count[READ] && !rl->count[WRITE]) {
+ smp_mb();
+ if (unlikely(waitqueue_active(&rl->drain)))
+ wake_up(&rl->drain);
+ }
}
#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
@@ -1889,12 +1885,14 @@ static void freed_request(request_queue_t *q, int rw, int priv)
* Returns !NULL on success, with queue_lock *not held*.
*/
static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
- gfp_t gfp_mask)
+ int gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
struct io_context *ioc = current_io_context(GFP_ATOMIC);
- int priv;
+
+ if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
+ goto out;
if (rl->count[rw]+1 >= q->nr_requests) {
/*
@@ -1939,14 +1937,9 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
rl->starved[rw] = 0;
if (rl->count[rw] >= queue_congestion_on_threshold(q))
set_queue_congested(q, rw);
-
- priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
- if (priv)
- rl->elvpriv++;
-
spin_unlock_irq(q->queue_lock);
- rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
+ rq = blk_alloc_request(q, rw, bio, gfp_mask);
if (!rq) {
/*
* Allocation failed presumably due to memory. Undo anything
@@ -1956,7 +1949,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
* wait queue, but this is pretty rare.
*/
spin_lock_irq(q->queue_lock);
- freed_request(q, rw, priv);
+ freed_request(q, rw);
/*
* in the very unlikely event that allocation failed and no
@@ -2026,7 +2019,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
return rq;
}
-struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
+struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
{
struct request *rq;
@@ -2258,7 +2251,7 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
* @gfp_mask: memory allocation flags
*/
int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
- unsigned int len, gfp_t gfp_mask)
+ unsigned int len, unsigned int gfp_mask)
{
struct bio *bio;
@@ -2440,15 +2433,13 @@ void disk_round_stats(struct gendisk *disk)
{
unsigned long now = jiffies;
- if (now == disk->stamp)
- return;
-
- if (disk->in_flight) {
- __disk_stat_add(disk, time_in_queue,
- disk->in_flight * (now - disk->stamp));
- __disk_stat_add(disk, io_ticks, (now - disk->stamp));
- }
+ __disk_stat_add(disk, time_in_queue,
+ disk->in_flight * (now - disk->stamp));
disk->stamp = now;
+
+ if (disk->in_flight)
+ __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
+ disk->stamp_idle = now;
}
/*
@@ -2463,8 +2454,6 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
if (unlikely(--req->ref_count))
return;
- elv_completed_request(q, req);
-
req->rq_status = RQ_INACTIVE;
req->rl = NULL;
@@ -2474,25 +2463,26 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
*/
if (rl) {
int rw = rq_data_dir(req);
- int priv = req->flags & REQ_ELVPRIV;
+
+ elv_completed_request(q, req);
BUG_ON(!list_empty(&req->queuelist));
blk_free_request(q, req);
- freed_request(q, rw, priv);
+ freed_request(q, rw);
}
}
void blk_put_request(struct request *req)
{
- unsigned long flags;
- request_queue_t *q = req->q;
-
/*
- * Gee, IDE calls in w/ NULL q. Fix IDE and remove the
- * following if (q) test.
+ * if req->rl isn't set, this request didnt originate from the
+ * block layer, so it's safe to just disregard it
*/
- if (q) {
+ if (req->rl) {
+ unsigned long flags;
+ request_queue_t *q = req->q;
+
spin_lock_irqsave(q->queue_lock, flags);
__blk_put_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2807,6 +2797,97 @@ static inline void blk_partition_remap(struct bio *bio)
}
}
+void blk_finish_queue_drain(request_queue_t *q)
+{
+ struct request_list *rl = &q->rq;
+ struct request *rq;
+ int requeued = 0;
+
+ spin_lock_irq(q->queue_lock);
+ clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
+
+ while (!list_empty(&q->drain_list)) {
+ rq = list_entry_rq(q->drain_list.next);
+
+ list_del_init(&rq->queuelist);
+ elv_requeue_request(q, rq);
+ requeued++;
+ }
+
+ if (requeued)
+ q->request_fn(q);
+
+ spin_unlock_irq(q->queue_lock);
+
+ wake_up(&rl->wait[0]);
+ wake_up(&rl->wait[1]);
+ wake_up(&rl->drain);
+}
+
+static int wait_drain(request_queue_t *q, struct request_list *rl, int dispatch)
+{
+ int wait = rl->count[READ] + rl->count[WRITE];
+
+ if (dispatch)
+ wait += !list_empty(&q->queue_head);
+
+ return wait;
+}
+
+/*
+ * We rely on the fact that only requests allocated through blk_alloc_request()
+ * have io scheduler private data structures associated with them. Any other
+ * type of request (allocated on stack or through kmalloc()) should not go
+ * to the io scheduler core, but be attached to the queue head instead.
+ */
+void blk_wait_queue_drained(request_queue_t *q, int wait_dispatch)
+{
+ struct request_list *rl = &q->rq;
+ DEFINE_WAIT(wait);
+
+ spin_lock_irq(q->queue_lock);
+ set_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
+
+ while (wait_drain(q, rl, wait_dispatch)) {
+ prepare_to_wait(&rl->drain, &wait, TASK_UNINTERRUPTIBLE);
+
+ if (wait_drain(q, rl, wait_dispatch)) {
+ __generic_unplug_device(q);
+ spin_unlock_irq(q->queue_lock);
+ io_schedule();
+ spin_lock_irq(q->queue_lock);
+ }
+
+ finish_wait(&rl->drain, &wait);
+ }
+
+ spin_unlock_irq(q->queue_lock);
+}
+
+/*
+ * block waiting for the io scheduler being started again.
+ */
+static inline void block_wait_queue_running(request_queue_t *q)
+{
+ DEFINE_WAIT(wait);
+
+ while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
+ struct request_list *rl = &q->rq;
+
+ prepare_to_wait_exclusive(&rl->drain, &wait,
+ TASK_UNINTERRUPTIBLE);
+
+ /*
+ * re-check the condition. avoids using prepare_to_wait()
+ * in the fast path (queue is running)
+ */
+ if (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))
+ io_schedule();
+
+ finish_wait(&rl->drain, &wait);
+ }
+}
+
static void handle_bad_sector(struct bio *bio)
{
char b[BDEVNAME_SIZE];
@@ -2902,6 +2983,8 @@ void generic_make_request(struct bio *bio)
if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
+ block_wait_queue_running(q);
+
/*
* If this device has partitions, remap block n
* of partition p to block n+start(p) of the disk.
@@ -3310,7 +3393,7 @@ void exit_io_context(void)
* but since the current task itself holds a reference, the context can be
* used in general code, so long as it stays within `current` context.
*/
-struct io_context *current_io_context(gfp_t gfp_flags)
+struct io_context *current_io_context(int gfp_flags)
{
struct task_struct *tsk = current;
struct io_context *ret;
@@ -3341,7 +3424,7 @@ EXPORT_SYMBOL(current_io_context);
*
* This is always called in the context of the task which submitted the I/O.
*/
-struct io_context *get_io_context(gfp_t gfp_flags)
+struct io_context *get_io_context(int gfp_flags)
{
struct io_context *ret;
ret = current_io_context(gfp_flags);
diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c
index 96c664af8d06..b35e08876dd4 100644
--- a/trunk/drivers/block/loop.c
+++ b/trunk/drivers/block/loop.c
@@ -881,7 +881,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
{
struct file *filp = lo->lo_backing_file;
- gfp_t gfp = lo->old_gfp_mask;
+ int gfp = lo->old_gfp_mask;
if (lo->lo_state != Lo_bound)
return -ENXIO;
diff --git a/trunk/drivers/block/noop-iosched.c b/trunk/drivers/block/noop-iosched.c
index f56b8edb06e4..b1730b62c37e 100644
--- a/trunk/drivers/block/noop-iosched.c
+++ b/trunk/drivers/block/noop-iosched.c
@@ -7,19 +7,57 @@
#include
#include
-static void elevator_noop_add_request(request_queue_t *q, struct request *rq)
+/*
+ * See if we can find a request that this buffer can be coalesced with.
+ */
+static int elevator_noop_merge(request_queue_t *q, struct request **req,
+ struct bio *bio)
+{
+ int ret;
+
+ ret = elv_try_last_merge(q, bio);
+ if (ret != ELEVATOR_NO_MERGE)
+ *req = q->last_merge;
+
+ return ret;
+}
+
+static void elevator_noop_merge_requests(request_queue_t *q, struct request *req,
+ struct request *next)
+{
+ list_del_init(&next->queuelist);
+}
+
+static void elevator_noop_add_request(request_queue_t *q, struct request *rq,
+ int where)
{
- elv_dispatch_add_tail(q, rq);
+ if (where == ELEVATOR_INSERT_FRONT)
+ list_add(&rq->queuelist, &q->queue_head);
+ else
+ list_add_tail(&rq->queuelist, &q->queue_head);
+
+ /*
+ * new merges must not precede this barrier
+ */
+ if (rq->flags & REQ_HARDBARRIER)
+ q->last_merge = NULL;
+ else if (!q->last_merge)
+ q->last_merge = rq;
}
-static int elevator_noop_dispatch(request_queue_t *q, int force)
+static struct request *elevator_noop_next_request(request_queue_t *q)
{
- return 0;
+ if (!list_empty(&q->queue_head))
+ return list_entry_rq(q->queue_head.next);
+
+ return NULL;
}
static struct elevator_type elevator_noop = {
.ops = {
- .elevator_dispatch_fn = elevator_noop_dispatch,
+ .elevator_merge_fn = elevator_noop_merge,
+ .elevator_merge_req_fn = elevator_noop_merge_requests,
+ .elevator_next_req_fn = elevator_noop_next_request,
.elevator_add_req_fn = elevator_noop_add_request,
},
.elevator_name = "noop",
diff --git a/trunk/drivers/block/rd.c b/trunk/drivers/block/rd.c
index 68c60a5bcdab..145c1fbffe01 100644
--- a/trunk/drivers/block/rd.c
+++ b/trunk/drivers/block/rd.c
@@ -348,7 +348,7 @@ static int rd_open(struct inode *inode, struct file *filp)
struct block_device *bdev = inode->i_bdev;
struct address_space *mapping;
unsigned bsize;
- gfp_t gfp_mask;
+ int gfp_mask;
inode = igrab(bdev->bd_inode);
rd_bdev[unit] = bdev;
diff --git a/trunk/drivers/block/sx8.c b/trunk/drivers/block/sx8.c
index 1ded3b433459..d57007b92f77 100644
--- a/trunk/drivers/block/sx8.c
+++ b/trunk/drivers/block/sx8.c
@@ -1,7 +1,7 @@
/*
* sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
*
- * Copyright 2004-2005 Red Hat, Inc.
+ * Copyright 2004 Red Hat, Inc.
*
* Author/maintainer: Jeff Garzik
*
@@ -31,6 +31,10 @@
#include
#include
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Promise SATA SX8 block driver");
+
#if 0
#define CARM_DEBUG
#define CARM_VERBOSE_DEBUG
@@ -41,35 +45,9 @@
#undef CARM_NDEBUG
#define DRV_NAME "sx8"
-#define DRV_VERSION "1.0"
+#define DRV_VERSION "0.8"
#define PFX DRV_NAME ": "
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Promise SATA SX8 block driver");
-MODULE_VERSION(DRV_VERSION);
-
-/*
- * SX8 hardware has a single message queue for all ATA ports.
- * When this driver was written, the hardware (firmware?) would
- * corrupt data eventually, if more than one request was outstanding.
- * As one can imagine, having 8 ports bottlenecking on a single
- * command hurts performance.
- *
- * Based on user reports, later versions of the hardware (firmware?)
- * seem to be able to survive with more than one command queued.
- *
- * Therefore, we default to the safe option -- 1 command -- but
- * allow the user to increase this.
- *
- * SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ),
- * but problems seem to occur when you exceed ~30, even on newer hardware.
- */
-static int max_queue = 1;
-module_param(max_queue, int, 0444);
-MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)");
-
-
#define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN)
/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
@@ -112,10 +90,12 @@ enum {
/* command message queue limits */
CARM_MAX_REQ = 64, /* max command msgs per host */
+ CARM_MAX_Q = 1, /* one command at a time */
CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */
/* S/G limits, host-wide and per-request */
CARM_MAX_REQ_SG = 32, /* max s/g entries per request */
+ CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
CARM_MAX_HOST_SG = 600, /* max s/g entries per host */
CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */
@@ -201,10 +181,6 @@ enum {
FL_DYN_MAJOR = (1 << 17),
};
-enum {
- CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
-};
-
enum scatter_gather_types {
SGT_32BIT = 0,
SGT_64BIT = 1,
@@ -242,6 +218,7 @@ static const char *state_name[] = {
struct carm_port {
unsigned int port_no;
+ unsigned int n_queued;
struct gendisk *disk;
struct carm_host *host;
@@ -471,7 +448,7 @@ static inline int carm_lookup_bucket(u32 msg_size)
for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
if (msg_size <= msg_sizes[i])
return i;
-
+
return -ENOENT;
}
@@ -532,7 +509,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
return NULL;
- for (i = 0; i < max_queue; i++)
+ for (i = 0; i < CARM_MAX_Q; i++)
if ((host->msg_alloc & (1ULL << i)) == 0) {
struct carm_request *crq = &host->req[i];
crq->port = NULL;
@@ -544,14 +521,14 @@ static struct carm_request *carm_get_request(struct carm_host *host)
assert(host->n_msgs <= CARM_MAX_REQ);
return crq;
}
-
+
DPRINTK("no request available, returning NULL\n");
return NULL;
}
static int carm_put_request(struct carm_host *host, struct carm_request *crq)
{
- assert(crq->tag < max_queue);
+ assert(crq->tag < CARM_MAX_Q);
if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
return -EINVAL; /* tried to clear a tag that was not active */
@@ -814,7 +791,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
int is_ok)
{
carm_end_request_queued(host, crq, is_ok);
- if (max_queue == 1)
+ if (CARM_MAX_Q == 1)
carm_round_robin(host);
else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
(host->hw_sg_used <= CARM_SG_LOW_WATER)) {
diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/char/n_tty.c
index c556f4d3ccd7..c9bdf544ed2c 100644
--- a/trunk/drivers/char/n_tty.c
+++ b/trunk/drivers/char/n_tty.c
@@ -62,7 +62,7 @@
static inline unsigned char *alloc_buf(void)
{
- gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ unsigned int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
if (PAGE_SIZE != N_TTY_BUF_SIZE)
return kmalloc(N_TTY_BUF_SIZE, prio);
diff --git a/trunk/drivers/ieee1394/eth1394.c b/trunk/drivers/ieee1394/eth1394.c
index c9e92d85c893..4802bbbb6dc9 100644
--- a/trunk/drivers/ieee1394/eth1394.c
+++ b/trunk/drivers/ieee1394/eth1394.c
@@ -1630,7 +1630,7 @@ static void ether1394_complete_cb(void *__ptask)
/* Transmit a packet (called by kernel) */
static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
{
- gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
struct eth1394hdr *eth;
struct eth1394_priv *priv = netdev_priv(dev);
int proto;
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c
index 378646b5a1b8..f6a8ac026557 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -524,7 +524,7 @@ void mthca_cmd_use_polling(struct mthca_dev *dev)
}
struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- gfp_t gfp_mask)
+ unsigned int gfp_mask)
{
struct mthca_mailbox *mailbox;
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h
index 18175bec84c2..65f976a13e02 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -248,7 +248,7 @@ void mthca_cmd_event(struct mthca_dev *dev, u16 token,
u8 status, u64 out_param);
struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- gfp_t gfp_mask);
+ unsigned int gfp_mask);
void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c
index 9ad8b3b6cfef..7bd7a4bec7b4 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -82,7 +82,7 @@ void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm)
}
struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
- gfp_t gfp_mask)
+ unsigned int gfp_mask)
{
struct mthca_icm *icm;
struct mthca_icm_chunk *chunk = NULL;
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.h b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.h
index 29433f295253..bafa51544aa3 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -77,7 +77,7 @@ struct mthca_icm_iter {
struct mthca_dev;
struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
- gfp_t gfp_mask);
+ unsigned int gfp_mask);
void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
diff --git a/trunk/drivers/md/bitmap.c b/trunk/drivers/md/bitmap.c
index 01654fcabc52..2fba2bbe72d8 100644
--- a/trunk/drivers/md/bitmap.c
+++ b/trunk/drivers/md/bitmap.c
@@ -91,7 +91,7 @@ int bitmap_active(struct bitmap *bitmap)
#define WRITE_POOL_SIZE 256
/* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(gfp_t gfp_flags, void *data)
+static void *write_pool_alloc(unsigned int gfp_flags, void *data)
{
return kmalloc(sizeof(struct page_list), gfp_flags);
}
diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c
index 28c1a628621f..b6148f6f7836 100644
--- a/trunk/drivers/md/dm-crypt.c
+++ b/trunk/drivers/md/dm-crypt.c
@@ -331,7 +331,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
{
struct bio *bio;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+ int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
unsigned int i;
/*
diff --git a/trunk/drivers/net/8139cp.c b/trunk/drivers/net/8139cp.c
index f822cd3025ff..bc537440ca02 100644
--- a/trunk/drivers/net/8139cp.c
+++ b/trunk/drivers/net/8139cp.c
@@ -1027,7 +1027,8 @@ static void cp_reset_hw (struct cp_private *cp)
if (!(cpr8(Cmd) & CmdReset))
return;
- schedule_timeout_uninterruptible(10);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
}
printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
@@ -1574,7 +1575,6 @@ static struct ethtool_ops cp_ethtool_ops = {
.set_wol = cp_set_wol,
.get_strings = cp_get_strings,
.get_ethtool_stats = cp_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1773,7 +1773,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->open = cp_open;
dev->stop = cp_close;
diff --git a/trunk/drivers/net/8139too.c b/trunk/drivers/net/8139too.c
index 30bee11c48bd..4c2cf7bbd252 100644
--- a/trunk/drivers/net/8139too.c
+++ b/trunk/drivers/net/8139too.c
@@ -552,8 +552,7 @@ const static struct {
{ "RTL-8100B/8139D",
HW_REVID(1, 1, 1, 0, 1, 0, 1),
- HasHltClk /* XXX undocumented? */
- | HasLWake,
+ HasLWake,
},
{ "RTL-8101",
@@ -971,7 +970,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* The Rtl8139-specific entries in the device structure. */
dev->open = rtl8139_open;
@@ -2467,7 +2465,6 @@ static struct ethtool_ops rtl8139_ethtool_ops = {
.get_strings = rtl8139_get_strings,
.get_stats_count = rtl8139_get_stats_count,
.get_ethtool_stats = rtl8139_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig
index 5148d47492a0..c748b0e16419 100644
--- a/trunk/drivers/net/Kconfig
+++ b/trunk/drivers/net/Kconfig
@@ -475,14 +475,6 @@ config SGI_IOC3_ETH_HW_TX_CSUM
the moment only acceleration of IPv4 is supported. This option
enables offloading for checksums on transmit. If unsure, say Y.
-config MIPS_SIM_NET
- tristate "MIPS simulator Network device (EXPERIMENTAL)"
- depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
- help
- The MIPSNET device is a simple Ethernet network device which is
- emulated by the MIPS Simulator.
- If you are not using a MIPSsim or are unsure, say N.
-
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
depends on NET_ETHERNET && SGI_IP32=y
@@ -2091,7 +2083,6 @@ config SPIDER_NET
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx
- select PHYLIB
help
This driver supports the Gigabit TSEC on the MPC85xx
family of chips, and the FEC on the 8540
@@ -2252,20 +2243,6 @@ config ISERIES_VETH
tristate "iSeries Virtual Ethernet driver support"
depends on PPC_ISERIES
-config RIONET
- tristate "RapidIO Ethernet over messaging driver support"
- depends on NETDEVICES && RAPIDIO
-
-config RIONET_TX_SIZE
- int "Number of outbound queue entries"
- depends on RIONET
- default "128"
-
-config RIONET_RX_SIZE
- int "Number of inbound queue entries"
- depends on RIONET
- default "128"
-
config FDDI
bool "FDDI driver support"
depends on (PCI || EISA)
diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile
index 1a84e0435f64..8aeec9f2495b 100644
--- a/trunk/drivers/net/Makefile
+++ b/trunk/drivers/net/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
#
# link order important here
@@ -64,7 +64,6 @@ obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
-obj-$(CONFIG_RIONET) += rionet.o
#
# end link order section
@@ -167,7 +166,6 @@ obj-$(CONFIG_EQUALIZER) += eql.o
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
-obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o
diff --git a/trunk/drivers/net/au1000_eth.c b/trunk/drivers/net/au1000_eth.c
index 78506911d656..c82b9cd1c924 100644
--- a/trunk/drivers/net/au1000_eth.c
+++ b/trunk/drivers/net/au1000_eth.c
@@ -151,6 +151,13 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
SUPPORTED_Autoneg
+static char *phy_link[] =
+{ "unknown",
+ "10Base2", "10BaseT",
+ "AUI",
+ "100BaseT", "100BaseTX", "100BaseFX"
+};
+
int bcm_5201_init(struct net_device *dev, int phy_addr)
{
s16 data;
@@ -778,7 +785,6 @@ static struct mii_chip_info {
{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
- {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
@@ -1039,7 +1045,7 @@ static int mii_probe (struct net_device * dev)
#endif
if (aup->mii->chip_info == NULL) {
- printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
+ printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
dev->name);
return -1;
}
@@ -1540,9 +1546,6 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
printk(KERN_ERR "%s: out of memory\n", dev->name);
goto err_out;
}
- aup->mii->next = NULL;
- aup->mii->chip_info = NULL;
- aup->mii->status = 0;
aup->mii->mii_control_reg = 0;
aup->mii->mii_data_reg = 0;
diff --git a/trunk/drivers/net/b44.c b/trunk/drivers/net/b44.c
index 282ebd15f011..94939f570f78 100644
--- a/trunk/drivers/net/b44.c
+++ b/trunk/drivers/net/b44.c
@@ -106,29 +106,6 @@ static int b44_poll(struct net_device *dev, int *budget);
static void b44_poll_controller(struct net_device *dev);
#endif
-static int dma_desc_align_mask;
-static int dma_desc_sync_size;
-
-static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
- dma_addr_t dma_base,
- unsigned long offset,
- enum dma_data_direction dir)
-{
- dma_sync_single_range_for_device(&pdev->dev, dma_base,
- offset & dma_desc_align_mask,
- dma_desc_sync_size, dir);
-}
-
-static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
- dma_addr_t dma_base,
- unsigned long offset,
- enum dma_data_direction dir)
-{
- dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
- offset & dma_desc_align_mask,
- dma_desc_sync_size, dir);
-}
-
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
{
return readl(bp->regs + reg);
@@ -691,11 +668,6 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dp->ctrl = cpu_to_le32(ctrl);
dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
- if (bp->flags & B44_FLAG_RX_RING_HACK)
- b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
- dest_idx * sizeof(dp),
- DMA_BIDIRECTIONAL);
-
return RX_PKT_BUF_SZ;
}
@@ -720,11 +692,6 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
pci_unmap_addr_set(dest_map, mapping,
pci_unmap_addr(src_map, mapping));
- if (bp->flags & B44_FLAG_RX_RING_HACK)
- b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
- src_idx * sizeof(src_desc),
- DMA_BIDIRECTIONAL);
-
ctrl = src_desc->ctrl;
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= cpu_to_le32(DESC_CTRL_EOT);
@@ -733,14 +700,8 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dest_desc->ctrl = ctrl;
dest_desc->addr = src_desc->addr;
-
src_map->skb = NULL;
- if (bp->flags & B44_FLAG_RX_RING_HACK)
- b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
- dest_idx * sizeof(dest_desc),
- DMA_BIDIRECTIONAL);
-
pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
@@ -998,11 +959,6 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
- if (bp->flags & B44_FLAG_TX_RING_HACK)
- b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
- entry * sizeof(bp->tx_ring[0]),
- DMA_TO_DEVICE);
-
entry = NEXT_TX(entry);
bp->tx_prod = entry;
@@ -1108,16 +1064,6 @@ static void b44_init_rings(struct b44 *bp)
memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
- if (bp->flags & B44_FLAG_RX_RING_HACK)
- dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
- DMA_TABLE_BYTES,
- PCI_DMA_BIDIRECTIONAL);
-
- if (bp->flags & B44_FLAG_TX_RING_HACK)
- dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
- DMA_TABLE_BYTES,
- PCI_DMA_TODEVICE);
-
for (i = 0; i < bp->rx_pending; i++) {
if (b44_alloc_rx_skb(bp, -1, i) < 0)
break;
@@ -1139,28 +1085,14 @@ static void b44_free_consistent(struct b44 *bp)
bp->tx_buffers = NULL;
}
if (bp->rx_ring) {
- if (bp->flags & B44_FLAG_RX_RING_HACK) {
- dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
- kfree(bp->rx_ring);
- } else
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->rx_ring, bp->rx_ring_dma);
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
- bp->flags &= ~B44_FLAG_RX_RING_HACK;
}
if (bp->tx_ring) {
- if (bp->flags & B44_FLAG_TX_RING_HACK) {
- dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
- kfree(bp->tx_ring);
- } else
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->tx_ring, bp->tx_ring_dma);
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
- bp->flags &= ~B44_FLAG_TX_RING_HACK;
}
}
@@ -1186,56 +1118,12 @@ static int b44_alloc_consistent(struct b44 *bp)
size = DMA_TABLE_BYTES;
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
- if (!bp->rx_ring) {
- /* Allocation may have failed due to pci_alloc_consistent
- insisting on use of GFP_DMA, which is more restrictive
- than necessary... */
- struct dma_desc *rx_ring;
- dma_addr_t rx_ring_dma;
-
- if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
- goto out_err;
-
- memset(rx_ring, 0, size);
- rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
-
- if (rx_ring_dma + size > B44_DMA_MASK) {
- kfree(rx_ring);
- goto out_err;
- }
-
- bp->rx_ring = rx_ring;
- bp->rx_ring_dma = rx_ring_dma;
- bp->flags |= B44_FLAG_RX_RING_HACK;
- }
+ if (!bp->rx_ring)
+ goto out_err;
bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
- if (!bp->tx_ring) {
- /* Allocation may have failed due to pci_alloc_consistent
- insisting on use of GFP_DMA, which is more restrictive
- than necessary... */
- struct dma_desc *tx_ring;
- dma_addr_t tx_ring_dma;
-
- if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
- goto out_err;
-
- memset(tx_ring, 0, size);
- tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
-
- if (tx_ring_dma + size > B44_DMA_MASK) {
- kfree(tx_ring);
- goto out_err;
- }
-
- bp->tx_ring = tx_ring;
- bp->tx_ring_dma = tx_ring_dma;
- bp->flags |= B44_FLAG_TX_RING_HACK;
- }
+ if (!bp->tx_ring)
+ goto out_err;
return 0;
@@ -1788,7 +1676,6 @@ static struct ethtool_ops b44_ethtool_ops = {
.set_pauseparam = b44_set_pauseparam,
.get_msglevel = b44_get_msglevel,
.set_msglevel = b44_set_msglevel,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1831,7 +1718,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->dev->dev_addr[3] = eeprom[80];
bp->dev->dev_addr[4] = eeprom[83];
bp->dev->dev_addr[5] = eeprom[82];
- memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
bp->phy_addr = eeprom[90] & 0x1f;
@@ -2085,12 +1971,6 @@ static struct pci_driver b44_driver = {
static int __init b44_init(void)
{
- unsigned int dma_desc_align_size = dma_get_cache_alignment();
-
- /* Setup paramaters for syncing RX/TX DMA descriptors */
- dma_desc_align_mask = ~(dma_desc_align_size - 1);
- dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
-
return pci_module_init(&b44_driver);
}
diff --git a/trunk/drivers/net/b44.h b/trunk/drivers/net/b44.h
index 593cb0ad4100..11c40a2e71c7 100644
--- a/trunk/drivers/net/b44.h
+++ b/trunk/drivers/net/b44.h
@@ -400,8 +400,6 @@ struct b44 {
#define B44_FLAG_ADV_100HALF 0x04000000
#define B44_FLAG_ADV_100FULL 0x08000000
#define B44_FLAG_INTERNAL_PHY 0x10000000
-#define B44_FLAG_RX_RING_HACK 0x20000000
-#define B44_FLAG_TX_RING_HACK 0x40000000
u32 rx_offset;
diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c
index 8032126fd589..f264ff162979 100644
--- a/trunk/drivers/net/bonding/bond_main.c
+++ b/trunk/drivers/net/bonding/bond_main.c
@@ -4241,43 +4241,6 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
return 0;
}
-static void bond_activebackup_xmit_copy(struct sk_buff *skb,
- struct bonding *bond,
- struct slave *slave)
-{
- struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
- struct ethhdr *eth_data;
- u8 *hwaddr;
- int res;
-
- if (!skb2) {
- printk(KERN_ERR DRV_NAME ": Error: "
- "bond_activebackup_xmit_copy(): skb_copy() failed\n");
- return;
- }
-
- skb2->mac.raw = (unsigned char *)skb2->data;
- eth_data = eth_hdr(skb2);
-
- /* Pick an appropriate source MAC address
- * -- use slave's perm MAC addr, unless used by bond
- * -- otherwise, borrow active slave's perm MAC addr
- * since that will not be used
- */
- hwaddr = slave->perm_hwaddr;
- if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
- hwaddr = bond->curr_active_slave->perm_hwaddr;
-
- /* Set source MAC address appropriately */
- memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
-
- res = bond_dev_queue_xmit(bond, skb2, slave->dev);
- if (res)
- dev_kfree_skb(skb2);
-
- return;
-}
-
/*
* in active-backup mode, we know that bond->curr_active_slave is always valid if
* the bond has a usable interface.
@@ -4294,26 +4257,10 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
goto out;
}
- if (!bond->curr_active_slave)
- goto out;
-
- /* Xmit IGMP frames on all slaves to ensure rapid fail-over
- for multicast traffic on snooping switches */
- if (skb->protocol == __constant_htons(ETH_P_IP) &&
- skb->nh.iph->protocol == IPPROTO_IGMP) {
- struct slave *slave, *active_slave;
- int i;
-
- active_slave = bond->curr_active_slave;
- bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
- active_slave->prev)
- if (IS_UP(slave->dev) &&
- (slave->link == BOND_LINK_UP))
- bond_activebackup_xmit_copy(skb, bond, slave);
+ if (bond->curr_active_slave) { /* one usable interface */
+ res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
}
- res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
-
out:
if (res) {
/* no suitable interface, frame not sent */
diff --git a/trunk/drivers/net/cassini.c b/trunk/drivers/net/cassini.c
index 50f43dbf31ae..2e617424d3fb 100644
--- a/trunk/drivers/net/cassini.c
+++ b/trunk/drivers/net/cassini.c
@@ -489,7 +489,7 @@ static int cas_page_free(struct cas *cp, cas_page_t *page)
/* local page allocation routines for the receive buffers. jumbo pages
* require at least 8K contiguous and 8K aligned buffers.
*/
-static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
+static cas_page_t *cas_page_alloc(struct cas *cp, const int flags)
{
cas_page_t *page;
@@ -561,7 +561,7 @@ static void cas_spare_free(struct cas *cp)
}
/* replenish spares if needed */
-static void cas_spare_recover(struct cas *cp, const gfp_t flags)
+static void cas_spare_recover(struct cas *cp, const int flags)
{
struct list_head list, *elem, *tmp;
int needed, i;
diff --git a/trunk/drivers/net/declance.c b/trunk/drivers/net/declance.c
index f130bdab3fd3..521c83137bf6 100644
--- a/trunk/drivers/net/declance.c
+++ b/trunk/drivers/net/declance.c
@@ -5,7 +5,7 @@
*
* adopted from sunlance.c by Richard van den Berg
*
- * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki
+ * Copyright (C) 2002, 2003 Maciej W. Rozycki
*
* additional sources:
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
@@ -57,15 +57,13 @@
#include
#include
-#include
-
#include
#include
#include
#include
#include
-#include
#include
+#include
static char version[] __devinitdata =
"declance.c: v0.009 by Linux MIPS DECstation task force\n";
@@ -81,6 +79,10 @@ MODULE_LICENSE("GPL");
#define PMAD_LANCE 2
#define PMAX_LANCE 3
+#ifndef CONFIG_TC
+unsigned long system_base;
+unsigned long dmaptr;
+#endif
#define LE_CSR0 0
#define LE_CSR1 1
@@ -235,7 +237,7 @@ struct lance_init_block {
/*
* This works *only* for the ring descriptors
*/
-#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
+#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
struct lance_private {
struct net_device *next;
@@ -695,13 +697,12 @@ static void lance_tx(struct net_device *dev)
spin_unlock(&lp->lock);
}
-static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
- struct pt_regs *regs)
+static void lance_dma_merr_int(const int irq, void *dev_id,
+ struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
printk("%s: DMA error\n", dev->name);
- return IRQ_HANDLED;
}
static irqreturn_t
@@ -1025,6 +1026,10 @@ static int __init dec_lance_init(const int type, const int slot)
unsigned long esar_base;
unsigned char *esar;
+#ifndef CONFIG_TC
+ system_base = KN01_LANCE_BASE;
+#endif
+
if (dec_lance_debug && version_printed++ == 0)
printk(version);
@@ -1057,16 +1062,16 @@ static int __init dec_lance_init(const int type, const int slot)
switch (type) {
#ifdef CONFIG_TC
case ASIC_LANCE:
- dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
+ dev->base_addr = system_base + IOASIC_LANCE;
/* buffer space for the on-board LANCE shared memory */
/*
* FIXME: ugly hack!
*/
- dev->mem_start = CKSEG1ADDR(0x00020000);
+ dev->mem_start = KSEG1ADDR(0x00020000);
dev->mem_end = dev->mem_start + 0x00020000;
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
- esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
+ esar_base = system_base + IOASIC_ESAR;
/* Workaround crash with booting KN04 2.1k from Disk */
memset((void *)dev->mem_start, 0,
@@ -1096,14 +1101,14 @@ static int __init dec_lance_init(const int type, const int slot)
/* Setup I/O ASIC LANCE DMA. */
lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
ioasic_write(IO_REG_LANCE_DMA_P,
- CPHYSADDR(dev->mem_start) << 3);
+ PHYSADDR(dev->mem_start) << 3);
break;
case PMAD_LANCE:
claim_tc_card(slot);
- dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
+ dev->mem_start = get_tc_base_addr(slot);
dev->base_addr = dev->mem_start + 0x100000;
dev->irq = get_tc_irq_nr(slot);
esar_base = dev->mem_start + 0x1c0002;
@@ -1132,9 +1137,9 @@ static int __init dec_lance_init(const int type, const int slot)
case PMAX_LANCE:
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
- dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
- dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
- esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
+ dev->base_addr = KN01_LANCE_BASE;
+ dev->mem_start = KN01_LANCE_BASE + 0x01000000;
+ esar_base = KN01_RTC_BASE + 1;
lp->dma_irq = -1;
/*
diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c
index eb169a8e8773..40887f09b681 100644
--- a/trunk/drivers/net/e100.c
+++ b/trunk/drivers/net/e100.c
@@ -2201,7 +2201,6 @@ static struct ethtool_ops e100_ethtool_ops = {
.phys_id = e100_phys_id,
.get_stats_count = e100_get_stats_count,
.get_ethtool_stats = e100_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
@@ -2352,8 +2351,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
e100_phy_init(nic);
memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
- memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
- if(!is_valid_ether_addr(netdev->perm_addr)) {
+ if(!is_valid_ether_addr(netdev->dev_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC address from "
"EEPROM, aborting.\n");
err = -EAGAIN;
diff --git a/trunk/drivers/net/e1000/e1000.h b/trunk/drivers/net/e1000/e1000.h
index 3f653a93e1bc..092757bc721f 100644
--- a/trunk/drivers/net/e1000/e1000.h
+++ b/trunk/drivers/net/e1000/e1000.h
@@ -72,10 +72,6 @@
#include
#include
#include
-#ifdef CONFIG_E1000_MQ
-#include
-#include
-#endif
#define BAR_0 0
#define BAR_1 1
@@ -169,33 +165,10 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
-struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
-struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
-
-struct e1000_tx_ring {
- /* pointer to the descriptor ring memory */
- void *desc;
- /* physical address of the descriptor ring */
- dma_addr_t dma;
- /* length of descriptor ring in bytes */
- unsigned int size;
- /* number of descriptors in the ring */
- unsigned int count;
- /* next descriptor to associate a buffer with */
- unsigned int next_to_use;
- /* next descriptor to check for DD status bit */
- unsigned int next_to_clean;
- /* array of buffer information structs */
- struct e1000_buffer *buffer_info;
-
- struct e1000_buffer previous_buffer_info;
- spinlock_t tx_lock;
- uint16_t tdh;
- uint16_t tdt;
- uint64_t pkt;
-};
+struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
-struct e1000_rx_ring {
+struct e1000_desc_ring {
/* pointer to the descriptor ring memory */
void *desc;
/* physical address of the descriptor ring */
@@ -213,10 +186,6 @@ struct e1000_rx_ring {
/* arrays of page information for packet split */
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
-
- uint16_t rdh;
- uint16_t rdt;
- uint64_t pkt;
};
#define E1000_DESC_UNUSED(R) \
@@ -258,10 +227,9 @@ struct e1000_adapter {
unsigned long led_status;
/* TX */
- struct e1000_tx_ring *tx_ring; /* One per active queue */
-#ifdef CONFIG_E1000_MQ
- struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
-#endif
+ struct e1000_desc_ring tx_ring;
+ struct e1000_buffer previous_buffer_info;
+ spinlock_t tx_lock;
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
@@ -278,33 +246,19 @@ struct e1000_adapter {
/* RX */
#ifdef CONFIG_E1000_NAPI
- boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
+ int work_to_do);
#else
- boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter);
#endif
- void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
- struct e1000_rx_ring *rx_ring; /* One per active queue */
-#ifdef CONFIG_E1000_NAPI
- struct net_device *polling_netdev; /* One per active queue */
-#endif
-#ifdef CONFIG_E1000_MQ
- struct net_device **cpu_netdev; /* per-cpu */
- struct call_async_data_struct rx_sched_call_data;
- int cpu_for_queue[4];
-#endif
- int num_queues;
-
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter);
+ struct e1000_desc_ring rx_ring;
uint64_t hw_csum_err;
uint64_t hw_csum_good;
- uint64_t rx_hdr_split;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
- unsigned int rx_ps_pages;
+ boolean_t rx_ps;
uint32_t gorcl;
uint64_t gorcl_old;
uint16_t rx_ps_bsize0;
@@ -324,8 +278,8 @@ struct e1000_adapter {
struct e1000_phy_stats phy_stats;
uint32_t test_icr;
- struct e1000_tx_ring test_tx_ring;
- struct e1000_rx_ring test_rx_ring;
+ struct e1000_desc_ring test_tx_ring;
+ struct e1000_desc_ring test_rx_ring;
int msg_enable;
diff --git a/trunk/drivers/net/e1000/e1000_ethtool.c b/trunk/drivers/net/e1000/e1000_ethtool.c
index 6b9acc7f94a3..f133ff0b0b94 100644
--- a/trunk/drivers/net/e1000/e1000_ethtool.c
+++ b/trunk/drivers/net/e1000/e1000_ethtool.c
@@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_reset(struct e1000_adapter *adapter);
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
extern void e1000_update_stats(struct e1000_adapter *adapter);
struct e1000_stats {
@@ -91,8 +91,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
- { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
- { "rx_header_split", E1000_STAT(rx_hdr_split) },
+ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
};
#define E1000_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -547,10 +546,8 @@ e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_write_eeprom(hw, first_word,
last_word - first_word + 1, eeprom_buff);
- /* Update the checksum over the first part of the EEPROM if needed
- * and flush shadow RAM for 82573 conrollers */
- if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
- (hw->mac_type == e1000_82573)))
+ /* Update the checksum over the first part of the EEPROM if needed */
+ if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
e1000_update_eeprom_checksum(hw);
kfree(eeprom_buff);
@@ -579,8 +576,8 @@ e1000_get_ringparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_mac_type mac_type = adapter->hw.mac_type;
- struct e1000_tx_ring *txdr = adapter->tx_ring;
- struct e1000_rx_ring *rxdr = adapter->rx_ring;
+ struct e1000_desc_ring *txdr = &adapter->tx_ring;
+ struct e1000_desc_ring *rxdr = &adapter->rx_ring;
ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
@@ -600,40 +597,20 @@ e1000_set_ringparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_mac_type mac_type = adapter->hw.mac_type;
- struct e1000_tx_ring *txdr, *tx_old, *tx_new;
- struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
- int i, err, tx_ring_size, rx_ring_size;
-
- tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
- rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
-
- if (netif_running(adapter->netdev))
- e1000_down(adapter);
+ struct e1000_desc_ring *txdr = &adapter->tx_ring;
+ struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+ struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
+ int err;
tx_old = adapter->tx_ring;
rx_old = adapter->rx_ring;
- adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
- if (!adapter->tx_ring) {
- err = -ENOMEM;
- goto err_setup_rx;
- }
- memset(adapter->tx_ring, 0, tx_ring_size);
-
- adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
- if (!adapter->rx_ring) {
- kfree(adapter->tx_ring);
- err = -ENOMEM;
- goto err_setup_rx;
- }
- memset(adapter->rx_ring, 0, rx_ring_size);
-
- txdr = adapter->tx_ring;
- rxdr = adapter->rx_ring;
-
if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
+ if(netif_running(adapter->netdev))
+ e1000_down(adapter);
+
rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -644,16 +621,11 @@ e1000_set_ringparam(struct net_device *netdev,
E1000_MAX_TXD : E1000_MAX_82544_TXD));
E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
- for (i = 0; i < adapter->num_queues; i++) {
- txdr[i].count = txdr->count;
- rxdr[i].count = rxdr->count;
- }
-
if(netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
- if ((err = e1000_setup_all_rx_resources(adapter)))
+ if((err = e1000_setup_rx_resources(adapter)))
goto err_setup_rx;
- if ((err = e1000_setup_all_tx_resources(adapter)))
+ if((err = e1000_setup_tx_resources(adapter)))
goto err_setup_tx;
/* save the new, restore the old in order to free it,
@@ -663,10 +635,8 @@ e1000_set_ringparam(struct net_device *netdev,
tx_new = adapter->tx_ring;
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
- e1000_free_all_rx_resources(adapter);
- e1000_free_all_tx_resources(adapter);
- kfree(tx_old);
- kfree(rx_old);
+ e1000_free_rx_resources(adapter);
+ e1000_free_tx_resources(adapter);
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
if((err = e1000_up(adapter)))
@@ -675,7 +645,7 @@ e1000_set_ringparam(struct net_device *netdev,
return 0;
err_setup_tx:
- e1000_free_all_rx_resources(adapter);
+ e1000_free_rx_resources(adapter);
err_setup_rx:
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
@@ -726,11 +696,6 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
* Some bits that get toggled are ignored.
*/
switch (adapter->hw.mac_type) {
- /* there are several bits on newer hardware that are r/w */
- case e1000_82571:
- case e1000_82572:
- toggle = 0x7FFFF3FF;
- break;
case e1000_82573:
toggle = 0x7FFFF033;
break;
@@ -933,8 +898,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
static void
e1000_free_desc_rings(struct e1000_adapter *adapter)
{
- struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
- struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i;
@@ -976,8 +941,8 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
static int
e1000_setup_desc_rings(struct e1000_adapter *adapter)
{
- struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
- struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
uint32_t rctl;
int size, i, ret_val;
@@ -1280,8 +1245,6 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
- case e1000_82571:
- case e1000_82572:
case e1000_82573:
return e1000_integrated_phy_loopback(adapter);
break;
@@ -1377,8 +1340,8 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int
e1000_run_loopback_test(struct e1000_adapter *adapter)
{
- struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
- struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i, j, k, l, lc, good_cnt, ret_val=0;
unsigned long time;
@@ -1546,7 +1509,6 @@ e1000_diag_test(struct net_device *netdev,
data[2] = 0;
data[3] = 0;
}
- msleep_interruptible(4 * 1000);
}
static void
@@ -1663,7 +1625,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82571) {
+ if(adapter->hw.mac_type < e1000_82573) {
if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1777,7 +1739,6 @@ struct ethtool_ops e1000_ethtool_ops = {
.phys_id = e1000_phys_id,
.get_stats_count = e1000_get_stats_count,
.get_ethtool_stats = e1000_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
void e1000_set_ethtool_ops(struct net_device *netdev)
diff --git a/trunk/drivers/net/e1000/e1000_hw.c b/trunk/drivers/net/e1000/e1000_hw.c
index 8fc876da43b4..045f5426ab9a 100644
--- a/trunk/drivers/net/e1000/e1000_hw.c
+++ b/trunk/drivers/net/e1000/e1000_hw.c
@@ -83,14 +83,14 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
static const
uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
- { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
- 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
- 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
- 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
- 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
- 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
- 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
- 104, 109, 114, 118, 121, 124};
+ { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
+ 22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
+ 32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
+ 43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
+ 57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
+ 73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
+ 91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
+ 108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
/******************************************************************************
@@ -286,6 +286,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
case E1000_DEV_ID_82546GB_PCIE:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -304,19 +305,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
- case E1000_DEV_ID_82571EB_COPPER:
- case E1000_DEV_ID_82571EB_FIBER:
- case E1000_DEV_ID_82571EB_SERDES:
- hw->mac_type = e1000_82571;
- break;
- case E1000_DEV_ID_82572EI_COPPER:
- case E1000_DEV_ID_82572EI_FIBER:
- case E1000_DEV_ID_82572EI_SERDES:
- hw->mac_type = e1000_82572;
- break;
case E1000_DEV_ID_82573E:
case E1000_DEV_ID_82573E_IAMT:
- case E1000_DEV_ID_82573L:
hw->mac_type = e1000_82573;
break;
default:
@@ -325,8 +315,6 @@ e1000_set_mac_type(struct e1000_hw *hw)
}
switch(hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
case e1000_82573:
hw->eeprom_semaphore_present = TRUE;
/* fall through */
@@ -363,8 +351,6 @@ e1000_set_media_type(struct e1000_hw *hw)
switch (hw->device_id) {
case E1000_DEV_ID_82545GM_SERDES:
case E1000_DEV_ID_82546GB_SERDES:
- case E1000_DEV_ID_82571EB_SERDES:
- case E1000_DEV_ID_82572EI_SERDES:
hw->media_type = e1000_media_type_internal_serdes;
break;
default:
@@ -537,8 +523,6 @@ e1000_reset_hw(struct e1000_hw *hw)
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
E1000_WRITE_FLUSH(hw);
/* fall through */
- case e1000_82571:
- case e1000_82572:
ret_val = e1000_get_auto_rd_done(hw);
if(ret_val)
/* We don't want to continue accessing MAC registers. */
@@ -699,9 +683,6 @@ e1000_init_hw(struct e1000_hw *hw)
switch (hw->mac_type) {
default:
break;
- case e1000_82571:
- case e1000_82572:
- ctrl |= (1 << 22);
case e1000_82573:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -713,26 +694,6 @@ e1000_init_hw(struct e1000_hw *hw)
e1000_enable_tx_pkt_filtering(hw);
}
- switch (hw->mac_type) {
- default:
- break;
- case e1000_82571:
- case e1000_82572:
- ctrl = E1000_READ_REG(hw, TXDCTL1);
- ctrl &= ~E1000_TXDCTL_WTHRESH;
- ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
- ctrl |= (1 << 22);
- E1000_WRITE_REG(hw, TXDCTL1, ctrl);
- break;
- }
-
-
-
- if (hw->mac_type == e1000_82573) {
- uint32_t gcr = E1000_READ_REG(hw, GCR);
- gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
- E1000_WRITE_REG(hw, GCR, gcr);
- }
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
@@ -917,14 +878,6 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_fiber_serdes_link");
- /* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
- * until explicitly turned off or a power cycle is performed. A read to
- * the register does not indicate its status. Therefore, we ensure
- * loopback mode is disabled during initialization.
- */
- if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
- E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
-
/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
* set when the optics detect a signal. On older adapters, it will be
* cleared when there is a signal. This applies to fiber media only.
@@ -2990,8 +2943,6 @@ e1000_phy_reset(struct e1000_hw *hw)
switch (hw->mac_type) {
case e1000_82541_rev_2:
- case e1000_82571:
- case e1000_82572:
ret_val = e1000_phy_hw_reset(hw);
if(ret_val)
return ret_val;
@@ -3030,16 +2981,6 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
DEBUGFUNC("e1000_detect_gig_phy");
- /* The 82571 firmware may still be configuring the PHY. In this
- * case, we cannot access the PHY until the configuration is done. So
- * we explicitly set the PHY values. */
- if(hw->mac_type == e1000_82571 ||
- hw->mac_type == e1000_82572) {
- hw->phy_id = IGP01E1000_I_PHY_ID;
- hw->phy_type = e1000_phy_igp_2;
- return E1000_SUCCESS;
- }
-
/* Read the PHY ID Registers to identify which PHY is onboard. */
ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
if(ret_val)
@@ -3393,21 +3334,6 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->use_eerd = FALSE;
eeprom->use_eewr = FALSE;
break;
- case e1000_82571:
- case e1000_82572:
- eeprom->type = e1000_eeprom_spi;
- eeprom->opcode_bits = 8;
- eeprom->delay_usec = 1;
- if (eecd & E1000_EECD_ADDR_BITS) {
- eeprom->page_size = 32;
- eeprom->address_bits = 16;
- } else {
- eeprom->page_size = 8;
- eeprom->address_bits = 8;
- }
- eeprom->use_eerd = FALSE;
- eeprom->use_eewr = FALSE;
- break;
case e1000_82573:
eeprom->type = e1000_eeprom_spi;
eeprom->opcode_bits = 8;
@@ -3617,25 +3543,24 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
eecd = E1000_READ_REG(hw, EECD);
if (hw->mac_type != e1000_82573) {
- /* Request EEPROM Access */
- if(hw->mac_type > e1000_82544) {
- eecd |= E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
+ /* Request EEPROM Access */
+ if(hw->mac_type > e1000_82544) {
+ eecd |= E1000_EECD_REQ;
+ E1000_WRITE_REG(hw, EECD, eecd);
+ eecd = E1000_READ_REG(hw, EECD);
+ while((!(eecd & E1000_EECD_GNT)) &&
+ (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+ i++;
+ udelay(5);
eecd = E1000_READ_REG(hw, EECD);
- while((!(eecd & E1000_EECD_GNT)) &&
- (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
- i++;
- udelay(5);
- eecd = E1000_READ_REG(hw, EECD);
- }
- if(!(eecd & E1000_EECD_GNT)) {
- eecd &= ~E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
- DEBUGOUT("Could not acquire EEPROM grant\n");
- e1000_put_hw_eeprom_semaphore(hw);
- return -E1000_ERR_EEPROM;
- }
}
+ if(!(eecd & E1000_EECD_GNT)) {
+ eecd &= ~E1000_EECD_REQ;
+ E1000_WRITE_REG(hw, EECD, eecd);
+ DEBUGOUT("Could not acquire EEPROM grant\n");
+ return -E1000_ERR_EEPROM;
+ }
+ }
}
/* Setup EEPROM for Read/Write */
@@ -4139,7 +4064,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* 82573 writes only through eewr */
+ /* 82573 reads only through eerd */
if(eeprom->use_eewr == TRUE)
return e1000_write_eeprom_eewr(hw, offset, words, data);
@@ -4428,16 +4353,9 @@ e1000_read_mac_addr(struct e1000_hw * hw)
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
}
- switch (hw->mac_type) {
- default:
- break;
- case e1000_82546:
- case e1000_82546_rev_3:
- case e1000_82571:
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
+ (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
hw->perm_mac_addr[5] ^= 0x01;
- break;
- }
for(i = 0; i < NODE_ADDRESS_SIZE; i++)
hw->mac_addr[i] = hw->perm_mac_addr[i];
@@ -4467,12 +4385,6 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
e1000_rar_set(hw, hw->mac_addr, 0);
rar_num = E1000_RAR_ENTRIES;
-
- /* Reserve a spot for the Locally Administered Address to work around
- * an 82571 issue in which a reset on one port will reload the MAC on
- * the other port. */
- if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
- rar_num -= 1;
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
for(i = 1; i < rar_num; i++) {
@@ -4515,12 +4427,6 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
num_rar_entry = E1000_RAR_ENTRIES;
- /* Reserve a spot for the Locally Administered Address to work around
- * an 82571 issue in which a reset on one port will reload the MAC on
- * the other port. */
- if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
- num_rar_entry -= 1;
-
for(i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -5078,6 +4984,7 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, ICTXQEC);
temp = E1000_READ_REG(hw, ICTXQMTC);
temp = E1000_READ_REG(hw, ICRXDMTC);
+
}
/******************************************************************************
@@ -5244,8 +5151,6 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
- case e1000_82571:
- case e1000_82572:
case e1000_82573:
hw->bus_type = e1000_bus_type_pci_express;
hw->bus_speed = e1000_bus_speed_2500;
@@ -5345,7 +5250,6 @@ e1000_get_cable_length(struct e1000_hw *hw,
int32_t ret_val;
uint16_t agc_value = 0;
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
- uint16_t max_agc = 0;
uint16_t i, phy_data;
uint16_t cable_length;
@@ -5434,40 +5338,6 @@ e1000_get_cable_length(struct e1000_hw *hw,
IGP01E1000_AGC_RANGE) : 0;
*max_length = e1000_igp_cable_length_table[agc_value] +
IGP01E1000_AGC_RANGE;
- } else if (hw->phy_type == e1000_phy_igp_2) {
- uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
- {IGP02E1000_PHY_AGC_A,
- IGP02E1000_PHY_AGC_B,
- IGP02E1000_PHY_AGC_C,
- IGP02E1000_PHY_AGC_D};
- /* Read the AGC registers for all channels */
- for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
- ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
- if (ret_val)
- return ret_val;
-
- /* Getting bits 15:9, which represent the combination of course and
- * fine gain values. The result is a number that can be put into
- * the lookup table to obtain the approximate cable length. */
- cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
- IGP02E1000_AGC_LENGTH_MASK;
-
- /* Remove min & max AGC values from calculation. */
- if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
- min_agc = cur_agc;
- if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
- max_agc = cur_agc;
-
- agc_value += e1000_igp_2_cable_length_table[cur_agc];
- }
-
- agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
- agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
-
- /* Calculate cable length with the error range of +/- 10 meters. */
- *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
- (agc_value - IGP02E1000_AGC_RANGE) : 0;
- *max_length = agc_value + IGP02E1000_AGC_RANGE;
}
return E1000_SUCCESS;
@@ -6595,8 +6465,6 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
default:
msec_delay(5);
break;
- case e1000_82571:
- case e1000_82572:
case e1000_82573:
while(timeout) {
if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
@@ -6626,31 +6494,10 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
int32_t
e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
- int32_t timeout = PHY_CFG_TIMEOUT;
- uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
-
DEBUGFUNC("e1000_get_phy_cfg_done");
- switch (hw->mac_type) {
- default:
- msec_delay(10);
- break;
- case e1000_82571:
- case e1000_82572:
- while (timeout) {
- if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
- break;
- else
- msec_delay(1);
- timeout--;
- }
-
- if (!timeout) {
- DEBUGOUT("MNG configuration cycle has not completed.\n");
- return -E1000_ERR_RESET;
- }
- break;
- }
+ /* Simply wait for 10ms */
+ msec_delay(10);
return E1000_SUCCESS;
}
@@ -6722,7 +6569,8 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
return;
swsm = E1000_READ_REG(hw, SWSM);
- swsm &= ~(E1000_SWSM_SWESMBI);
+ /* Release both semaphores. */
+ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
E1000_WRITE_REG(hw, SWSM, swsm);
}
@@ -6758,8 +6606,6 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* if this is the case. We read FWSM to determine the manageability mode.
*/
switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
case e1000_82573:
fwsm = E1000_READ_REG(hw, FWSM);
if((fwsm & E1000_FWSM_MODE_MASK) != 0)
diff --git a/trunk/drivers/net/e1000/e1000_hw.h b/trunk/drivers/net/e1000/e1000_hw.h
index 4f2c196dc314..51c2b3a18b6f 100644
--- a/trunk/drivers/net/e1000/e1000_hw.h
+++ b/trunk/drivers/net/e1000/e1000_hw.h
@@ -57,8 +57,6 @@ typedef enum {
e1000_82541_rev_2,
e1000_82547,
e1000_82547_rev_2,
- e1000_82571,
- e1000_82572,
e1000_82573,
e1000_num_macs
} e1000_mac_type;
@@ -480,16 +478,10 @@ uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
-#define E1000_DEV_ID_82571EB_COPPER 0x105E
-#define E1000_DEV_ID_82571EB_FIBER 0x105F
-#define E1000_DEV_ID_82571EB_SERDES 0x1060
-#define E1000_DEV_ID_82572EI_COPPER 0x107D
-#define E1000_DEV_ID_82572EI_FIBER 0x107E
-#define E1000_DEV_ID_82572EI_SERDES 0x107F
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
-#define E1000_DEV_ID_82573L 0x109A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -841,8 +833,6 @@ struct e1000_ffvt_entry {
#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-#define E1000_DISABLE_SERDES_LOOPBACK 0x0400
-
/* Register Set. (82543, 82544)
*
* Registers are defined to be 32 bits and should be accessed as 32 bit values.
@@ -863,7 +853,6 @@ struct e1000_ffvt_entry {
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */
-#define E1000_SCTL 0x00024 /* SerDes Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
@@ -875,12 +864,6 @@ struct e1000_ffvt_entry {
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
#define E1000_RCTL 0x00100 /* RX Control - RW */
-#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
-#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
-#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
-#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
-#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
-#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
@@ -912,12 +895,6 @@ struct e1000_ffvt_entry {
#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
-#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
-#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
-#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
-#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
-#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
-#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
@@ -1003,15 +980,15 @@ struct e1000_ffvt_entry {
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
-#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
+#define E1000_IAC 0x4100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
@@ -1041,14 +1018,6 @@ struct e1000_ffvt_entry {
#define E1000_FWSM 0x05B54 /* FW Semaphore */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Inteface Control */
-
-/* RSS registers */
-#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
-#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
-#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */
-#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */
-#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
-#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
/* Register Set (82542)
*
* Some of the 82542 registers are located at different offsets than they are
@@ -1063,7 +1032,6 @@ struct e1000_ffvt_entry {
#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
#define E1000_82542_FLA E1000_FLA
#define E1000_82542_MDIC E1000_MDIC
-#define E1000_82542_SCTL E1000_SCTL
#define E1000_82542_FCAL E1000_FCAL
#define E1000_82542_FCAH E1000_FCAH
#define E1000_82542_FCT E1000_FCT
@@ -1081,18 +1049,6 @@ struct e1000_ffvt_entry {
#define E1000_82542_RDLEN 0x00118
#define E1000_82542_RDH 0x00120
#define E1000_82542_RDT 0x00128
-#define E1000_82542_RDTR0 E1000_82542_RDTR
-#define E1000_82542_RDBAL0 E1000_82542_RDBAL
-#define E1000_82542_RDBAH0 E1000_82542_RDBAH
-#define E1000_82542_RDLEN0 E1000_82542_RDLEN
-#define E1000_82542_RDH0 E1000_82542_RDH
-#define E1000_82542_RDT0 E1000_82542_RDT
-#define E1000_82542_RDTR1 0x00130
-#define E1000_82542_RDBAL1 0x00138
-#define E1000_82542_RDBAH1 0x0013C
-#define E1000_82542_RDLEN1 0x00140
-#define E1000_82542_RDH1 0x00148
-#define E1000_82542_RDT1 0x00150
#define E1000_82542_FCRTH 0x00160
#define E1000_82542_FCRTL 0x00168
#define E1000_82542_FCTTV E1000_FCTTV
@@ -1241,13 +1197,6 @@ struct e1000_ffvt_entry {
#define E1000_82542_ICRXOC E1000_ICRXOC
#define E1000_82542_HICR E1000_HICR
-#define E1000_82542_CPUVEC E1000_CPUVEC
-#define E1000_82542_MRQC E1000_MRQC
-#define E1000_82542_RETA E1000_RETA
-#define E1000_82542_RSSRK E1000_RSSRK
-#define E1000_82542_RSSIM E1000_RSSIM
-#define E1000_82542_RSSIR E1000_RSSIR
-
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
uint64_t crcerrs;
@@ -1387,7 +1336,6 @@ struct e1000_hw {
boolean_t serdes_link_down;
boolean_t tbi_compatibility_en;
boolean_t tbi_compatibility_on;
- boolean_t laa_is_present;
boolean_t phy_reset_disable;
boolean_t fc_send_xon;
boolean_t fc_strict_ieee;
@@ -1426,7 +1374,6 @@ struct e1000_hw {
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
-#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
@@ -1544,8 +1491,6 @@ struct e1000_hw {
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
-#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */
-#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
@@ -1579,7 +1524,6 @@ struct e1000_hw {
#define E1000_LEDCTL_LED2_BLINK 0x00800000
#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
#define E1000_LEDCTL_LED3_MODE_SHIFT 24
-#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000
#define E1000_LEDCTL_LED3_IVRT 0x40000000
#define E1000_LEDCTL_LED3_BLINK 0x80000000
@@ -1840,16 +1784,6 @@ struct e1000_hw {
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
-/* Multiple Receive Queue Control */
-#define E1000_MRQC_ENABLE_MASK 0x00000003
-#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
-#define E1000_MRQC_ENABLE_RSS_INT 0x00000004
-#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
-#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
-#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
-#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00040000
-#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
-#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
@@ -1994,7 +1928,6 @@ struct e1000_host_command_info {
#define E1000_MDALIGN 4096
#define E1000_GCR_BEM32 0x00400000
-#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
#define E1000_FACTPS_LAN0_VALID 0x00000004
@@ -2047,7 +1980,6 @@ struct e1000_host_command_info {
/* EEPROM Word Offsets */
#define EEPROM_COMPAT 0x0003
#define EEPROM_ID_LED_SETTINGS 0x0004
-#define EEPROM_VERSION 0x0005
#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
#define EEPROM_PHY_CLASS_WORD 0x0007
#define EEPROM_INIT_CONTROL1_REG 0x000A
@@ -2058,8 +1990,6 @@ struct e1000_host_command_info {
#define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F
-#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
-
/* Word definitions for ID LED Settings */
#define ID_LED_RESERVED_0000 0x0000
#define ID_LED_RESERVED_FFFF 0xFFFF
@@ -2178,8 +2108,6 @@ struct e1000_host_command_info {
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
#define E1000_PBA_30K 0x001E
-#define E1000_PBA_32K 0x0020
-#define E1000_PBA_38K 0x0026
#define E1000_PBA_40K 0x0028
#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
@@ -2664,11 +2592,11 @@ struct e1000_host_command_info {
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
-#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
/* The precision error of the cable length is +/- 10 meters */
#define IGP01E1000_AGC_RANGE 10
-#define IGP02E1000_AGC_RANGE 15
+#define IGP02E1000_AGC_RANGE 10
/* IGP01E1000 PCS Initialization register */
/* bits 3:6 in the PCS registers stores the channels polarity */
diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c
index 6b72f6acdd54..ee687c902a20 100644
--- a/trunk/drivers/net/e1000/e1000_main.c
+++ b/trunk/drivers/net/e1000/e1000_main.c
@@ -43,7 +43,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
+#define DRV_VERSION "6.0.60-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -80,9 +80,6 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1026),
INTEL_E1000_ETHERNET_DEVICE(0x1027),
INTEL_E1000_ETHERNET_DEVICE(0x1028),
- INTEL_E1000_ETHERNET_DEVICE(0x105E),
- INTEL_E1000_ETHERNET_DEVICE(0x105F),
- INTEL_E1000_ETHERNET_DEVICE(0x1060),
INTEL_E1000_ETHERNET_DEVICE(0x1075),
INTEL_E1000_ETHERNET_DEVICE(0x1076),
INTEL_E1000_ETHERNET_DEVICE(0x1077),
@@ -91,13 +88,10 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x107A),
INTEL_E1000_ETHERNET_DEVICE(0x107B),
INTEL_E1000_ETHERNET_DEVICE(0x107C),
- INTEL_E1000_ETHERNET_DEVICE(0x107D),
- INTEL_E1000_ETHERNET_DEVICE(0x107E),
- INTEL_E1000_ETHERNET_DEVICE(0x107F),
INTEL_E1000_ETHERNET_DEVICE(0x108A),
INTEL_E1000_ETHERNET_DEVICE(0x108B),
INTEL_E1000_ETHERNET_DEVICE(0x108C),
- INTEL_E1000_ETHERNET_DEVICE(0x109A),
+ INTEL_E1000_ETHERNET_DEVICE(0x1099),
/* required last entry */
{0,}
};
@@ -108,18 +102,10 @@ int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter);
void e1000_reset(struct e1000_adapter *adapter);
int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-int e1000_setup_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *txdr);
-int e1000_setup_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rxdr);
-void e1000_free_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring);
-void e1000_free_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+int e1000_setup_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_rx_resources(struct e1000_adapter *adapter);
void e1000_update_stats(struct e1000_adapter *adapter);
/* Local Function Prototypes */
@@ -128,22 +114,14 @@ static int e1000_init_module(void);
static void e1000_exit_module(void);
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void __devexit e1000_remove(struct pci_dev *pdev);
-static int e1000_alloc_queues(struct e1000_adapter *adapter);
-#ifdef CONFIG_E1000_MQ
-static void e1000_setup_queue_mapping(struct e1000_adapter *adapter);
-#endif
static int e1000_sw_init(struct e1000_adapter *adapter);
static int e1000_open(struct net_device *netdev);
static int e1000_close(struct net_device *netdev);
static void e1000_configure_tx(struct e1000_adapter *adapter);
static void e1000_configure_rx(struct e1000_adapter *adapter);
static void e1000_setup_rctl(struct e1000_adapter *adapter);
-static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
-static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring);
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data);
@@ -154,26 +132,19 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring);
+static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
#ifdef CONFIG_E1000_NAPI
-static int e1000_clean(struct net_device *poll_dev, int *budget);
+static int e1000_clean(struct net_device *netdev, int *budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
#else
-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
#endif
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -201,11 +172,6 @@ static int e1000_resume(struct pci_dev *pdev);
static void e1000_netpoll (struct net_device *netdev);
#endif
-#ifdef CONFIG_E1000_MQ
-/* for multiple Rx queues */
-void e1000_rx_schedule(void *data);
-#endif
-
/* Exported from other modules */
extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -323,7 +289,7 @@ int
e1000_up(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int i, err;
+ int err;
/* hardware has been reset, we need to reload some things */
@@ -342,8 +308,7 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- for (i = 0; i < adapter->num_queues; i++)
- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
+ adapter->alloc_rx_buf(adapter);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2) {
@@ -379,9 +344,6 @@ e1000_down(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
e1000_irq_disable(adapter);
-#ifdef CONFIG_E1000_MQ
- while (atomic_read(&adapter->rx_sched_call_data.count) != 0);
-#endif
free_irq(adapter->pdev->irq, netdev);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2 &&
@@ -401,10 +363,11 @@ e1000_down(struct e1000_adapter *adapter)
netif_stop_queue(netdev);
e1000_reset(adapter);
- e1000_clean_all_tx_rings(adapter);
- e1000_clean_all_rx_rings(adapter);
+ e1000_clean_tx_ring(adapter);
+ e1000_clean_rx_ring(adapter);
- /* If WoL is not enabled and management mode is not IAMT
+ /* If WoL is not enabled
+ * and management mode is not IAMT
* Power down the PHY so no link is implied when interface is down */
if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper &&
@@ -435,10 +398,6 @@ e1000_reset(struct e1000_adapter *adapter)
case e1000_82547_rev_2:
pba = E1000_PBA_30K;
break;
- case e1000_82571:
- case e1000_82572:
- pba = E1000_PBA_38K;
- break;
case e1000_82573:
pba = E1000_PBA_12K;
break;
@@ -516,7 +475,6 @@ e1000_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct e1000_adapter *adapter;
unsigned long mmio_start, mmio_len;
- uint32_t ctrl_ext;
uint32_t swsm;
static int cards_found = 0;
@@ -656,9 +614,8 @@ e1000_probe(struct pci_dev *pdev,
if(e1000_read_mac_addr(&adapter->hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
- memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->perm_addr)) {
+ if(!is_valid_ether_addr(netdev->dev_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
@@ -730,12 +687,6 @@ e1000_probe(struct pci_dev *pdev,
/* Let firmware know the driver has taken over */
switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -780,11 +731,7 @@ e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t ctrl_ext;
uint32_t manc, swsm;
-#ifdef CONFIG_E1000_NAPI
- int i;
-#endif
flush_scheduled_work();
@@ -798,12 +745,6 @@ e1000_remove(struct pci_dev *pdev)
}
switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -815,27 +756,13 @@ e1000_remove(struct pci_dev *pdev)
}
unregister_netdev(netdev);
-#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++)
- __dev_put(&adapter->polling_netdev[i]);
-#endif
if(!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
- kfree(adapter->polling_netdev);
-#endif
-
iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev);
-#ifdef CONFIG_E1000_MQ
- free_percpu(adapter->cpu_netdev);
- free_percpu(adapter->cpu_tx_ring);
-#endif
free_netdev(netdev);
pci_disable_device(pdev);
@@ -856,9 +783,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
-#ifdef CONFIG_E1000_NAPI
- int i;
-#endif
/* PCI config space info */
@@ -916,122 +840,13 @@ e1000_sw_init(struct e1000_adapter *adapter)
hw->master_slave = E1000_MASTER_SLAVE;
}
-#ifdef CONFIG_E1000_MQ
- /* Number of supported queues */
- switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
- adapter->num_queues = 2;
- break;
- default:
- adapter->num_queues = 1;
- break;
- }
- adapter->num_queues = min(adapter->num_queues, num_online_cpus());
-#else
- adapter->num_queues = 1;
-#endif
-
- if (e1000_alloc_queues(adapter)) {
- DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
- return -ENOMEM;
- }
-
-#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++) {
- adapter->polling_netdev[i].priv = adapter;
- adapter->polling_netdev[i].poll = &e1000_clean;
- adapter->polling_netdev[i].weight = 64;
- dev_hold(&adapter->polling_netdev[i]);
- set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
- }
-#endif
-
-#ifdef CONFIG_E1000_MQ
- e1000_setup_queue_mapping(adapter);
-#endif
-
atomic_set(&adapter->irq_sem, 1);
spin_lock_init(&adapter->stats_lock);
+ spin_lock_init(&adapter->tx_lock);
return 0;
}
-/**
- * e1000_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time. The polling_netdev array is
- * intended for Multiqueue, but should work fine with a single queue.
- **/
-
-static int __devinit
-e1000_alloc_queues(struct e1000_adapter *adapter)
-{
- int size;
-
- size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
- adapter->tx_ring = kmalloc(size, GFP_KERNEL);
- if (!adapter->tx_ring)
- return -ENOMEM;
- memset(adapter->tx_ring, 0, size);
-
- size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
- adapter->rx_ring = kmalloc(size, GFP_KERNEL);
- if (!adapter->rx_ring) {
- kfree(adapter->tx_ring);
- return -ENOMEM;
- }
- memset(adapter->rx_ring, 0, size);
-
-#ifdef CONFIG_E1000_NAPI
- size = sizeof(struct net_device) * adapter->num_queues;
- adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
- if (!adapter->polling_netdev) {
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
- return -ENOMEM;
- }
- memset(adapter->polling_netdev, 0, size);
-#endif
-
- return E1000_SUCCESS;
-}
-
-#ifdef CONFIG_E1000_MQ
-static void __devinit
-e1000_setup_queue_mapping(struct e1000_adapter *adapter)
-{
- int i, cpu;
-
- adapter->rx_sched_call_data.func = e1000_rx_schedule;
- adapter->rx_sched_call_data.info = adapter->netdev;
- cpus_clear(adapter->rx_sched_call_data.cpumask);
-
- adapter->cpu_netdev = alloc_percpu(struct net_device *);
- adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
-
- lock_cpu_hotplug();
- i = 0;
- for_each_online_cpu(cpu) {
- *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
- /* This is incomplete because we'd like to assign separate
- * physical cpus to these netdev polling structures and
- * avoid saturating a subset of cpus.
- */
- if (i < adapter->num_queues) {
- *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
- adapter->cpu_for_queue[i] = cpu;
- } else
- *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
-
- i++;
- }
- unlock_cpu_hotplug();
-}
-#endif
-
/**
* e1000_open - Called when a network interface is made active
* @netdev: network interface device structure
@@ -1053,12 +868,12 @@ e1000_open(struct net_device *netdev)
/* allocate transmit descriptors */
- if ((err = e1000_setup_all_tx_resources(adapter)))
+ if((err = e1000_setup_tx_resources(adapter)))
goto err_setup_tx;
/* allocate receive descriptors */
- if ((err = e1000_setup_all_rx_resources(adapter)))
+ if((err = e1000_setup_rx_resources(adapter)))
goto err_setup_rx;
if((err = e1000_up(adapter)))
@@ -1072,9 +887,9 @@ e1000_open(struct net_device *netdev)
return E1000_SUCCESS;
err_up:
- e1000_free_all_rx_resources(adapter);
+ e1000_free_rx_resources(adapter);
err_setup_rx:
- e1000_free_all_tx_resources(adapter);
+ e1000_free_tx_resources(adapter);
err_setup_tx:
e1000_reset(adapter);
@@ -1100,8 +915,8 @@ e1000_close(struct net_device *netdev)
e1000_down(adapter);
- e1000_free_all_tx_resources(adapter);
- e1000_free_all_rx_resources(adapter);
+ e1000_free_tx_resources(adapter);
+ e1000_free_rx_resources(adapter);
if((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
@@ -1136,15 +951,14 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
/**
* e1000_setup_tx_resources - allocate Tx resources (Descriptors)
* @adapter: board private structure
- * @txdr: tx descriptor ring (for a specific queue) to setup
*
* Return 0 on success, negative on failure
**/
int
-e1000_setup_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *txdr)
+e1000_setup_tx_resources(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *txdr = &adapter->tx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
@@ -1156,7 +970,6 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
- memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
/* round up to nearest 4K */
@@ -1205,40 +1018,10 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
txdr->next_to_use = 0;
txdr->next_to_clean = 0;
- spin_lock_init(&txdr->tx_lock);
return 0;
}
-/**
- * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
- * (Descriptors) for all queues
- * @adapter: board private structure
- *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not). It is the
- * callers duty to clean those orphaned rings.
- *
- * Return 0 on success, negative on failure
- **/
-
-int
-e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
-{
- int i, err = 0;
-
- for (i = 0; i < adapter->num_queues; i++) {
- err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
- if (err) {
- DPRINTK(PROBE, ERR,
- "Allocation for Tx Queue %u failed\n", i);
- break;
- }
- }
-
- return err;
-}
-
/**
* e1000_configure_tx - Configure 8254x Transmit Unit after Reset
* @adapter: board private structure
@@ -1249,43 +1032,23 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
static void
e1000_configure_tx(struct e1000_adapter *adapter)
{
- uint64_t tdba;
- struct e1000_hw *hw = &adapter->hw;
- uint32_t tdlen, tctl, tipg, tarc;
+ uint64_t tdba = adapter->tx_ring.dma;
+ uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
+ uint32_t tctl, tipg;
+
+ E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
+
+ E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
/* Setup the HW Tx Head and Tail descriptor pointers */
- switch (adapter->num_queues) {
- case 2:
- tdba = adapter->tx_ring[1].dma;
- tdlen = adapter->tx_ring[1].count *
- sizeof(struct e1000_tx_desc);
- E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32));
- E1000_WRITE_REG(hw, TDLEN1, tdlen);
- E1000_WRITE_REG(hw, TDH1, 0);
- E1000_WRITE_REG(hw, TDT1, 0);
- adapter->tx_ring[1].tdh = E1000_TDH1;
- adapter->tx_ring[1].tdt = E1000_TDT1;
- /* Fall Through */
- case 1:
- default:
- tdba = adapter->tx_ring[0].dma;
- tdlen = adapter->tx_ring[0].count *
- sizeof(struct e1000_tx_desc);
- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
- E1000_WRITE_REG(hw, TDLEN, tdlen);
- E1000_WRITE_REG(hw, TDH, 0);
- E1000_WRITE_REG(hw, TDT, 0);
- adapter->tx_ring[0].tdh = E1000_TDH;
- adapter->tx_ring[0].tdt = E1000_TDT;
- break;
- }
+ E1000_WRITE_REG(&adapter->hw, TDH, 0);
+ E1000_WRITE_REG(&adapter->hw, TDT, 0);
/* Set the default values for the Tx Inter Packet Gap timer */
- switch (hw->mac_type) {
+ switch (adapter->hw.mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
tipg = DEFAULT_82542_TIPG_IPGT;
@@ -1293,81 +1056,67 @@ e1000_configure_tx(struct e1000_adapter *adapter)
tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
break;
default:
- if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes)
+ if(adapter->hw.media_type == e1000_media_type_fiber ||
+ adapter->hw.media_type == e1000_media_type_internal_serdes)
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
else
tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
}
- E1000_WRITE_REG(hw, TIPG, tipg);
+ E1000_WRITE_REG(&adapter->hw, TIPG, tipg);
/* Set the Tx Interrupt Delay register */
- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
- if (hw->mac_type >= e1000_82540)
- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
+ E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
+ if(adapter->hw.mac_type >= e1000_82540)
+ E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay);
/* Program the Transmit Control Register */
- tctl = E1000_READ_REG(hw, TCTL);
+ tctl = E1000_READ_REG(&adapter->hw, TCTL);
tctl &= ~E1000_TCTL_CT;
- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
+ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
- E1000_WRITE_REG(hw, TCTL, tctl);
+ E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
- if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
- tarc = E1000_READ_REG(hw, TARC0);
- tarc |= ((1 << 25) | (1 << 21));
- E1000_WRITE_REG(hw, TARC0, tarc);
- tarc = E1000_READ_REG(hw, TARC1);
- tarc |= (1 << 25);
- if (tctl & E1000_TCTL_MULR)
- tarc &= ~(1 << 28);
- else
- tarc |= (1 << 28);
- E1000_WRITE_REG(hw, TARC1, tarc);
- }
-
- e1000_config_collision_dist(hw);
+ e1000_config_collision_dist(&adapter->hw);
/* Setup Transmit Descriptor Settings for eop descriptor */
adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
E1000_TXD_CMD_IFCS;
- if (hw->mac_type < e1000_82543)
+ if(adapter->hw.mac_type < e1000_82543)
adapter->txd_cmd |= E1000_TXD_CMD_RPS;
else
adapter->txd_cmd |= E1000_TXD_CMD_RS;
/* Cache if we're 82544 running in PCI-X because we'll
* need this to apply a workaround later in the send path. */
- if (hw->mac_type == e1000_82544 &&
- hw->bus_type == e1000_bus_type_pcix)
+ if(adapter->hw.mac_type == e1000_82544 &&
+ adapter->hw.bus_type == e1000_bus_type_pcix)
adapter->pcix_82544 = 1;
}
/**
* e1000_setup_rx_resources - allocate Rx resources (Descriptors)
* @adapter: board private structure
- * @rxdr: rx descriptor ring (for a specific queue) to setup
*
* Returns 0 on success, negative on failure
**/
int
-e1000_setup_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rxdr)
+e1000_setup_rx_resources(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
rxdr->buffer_info = vmalloc(size);
- if (!rxdr->buffer_info) {
+ if(!rxdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
@@ -1407,13 +1156,13 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if (!rxdr->desc) {
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory for the receive descriptor ring\n");
+ if(!rxdr->desc) {
setup_rx_desc_die:
vfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
kfree(rxdr->ps_page_dma);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
}
@@ -1425,12 +1174,9 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
"at %p\n", rxdr->size, rxdr->desc);
/* Try again, without freeing the previous */
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+ if(!rxdr->desc) {
/* Failed allocation, critical failure */
- if (!rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory "
- "for the receive descriptor ring\n");
goto setup_rx_desc_die;
}
@@ -1442,7 +1188,10 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
DPRINTK(PROBE, ERR,
"Unable to allocate aligned memory "
"for the receive descriptor ring\n");
- goto setup_rx_desc_die;
+ vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ kfree(rxdr->ps_page_dma);
+ return -ENOMEM;
} else {
/* Free old allocation, new allocation was successful */
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
@@ -1456,49 +1205,16 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
return 0;
}
-/**
- * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
- * (Descriptors) for all queues
- * @adapter: board private structure
- *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not). It is the
- * callers duty to clean those orphaned rings.
- *
- * Return 0 on success, negative on failure
- **/
-
-int
-e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
-{
- int i, err = 0;
-
- for (i = 0; i < adapter->num_queues; i++) {
- err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
- if (err) {
- DPRINTK(PROBE, ERR,
- "Allocation for Rx Queue %u failed\n", i);
- break;
- }
- }
-
- return err;
-}
-
/**
* e1000_setup_rctl - configure the receive control registers
* @adapter: Board private structure
**/
-#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
- (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
+
static void
e1000_setup_rctl(struct e1000_adapter *adapter)
{
uint32_t rctl, rfctl;
uint32_t psrctl = 0;
-#ifdef CONFIG_E1000_PACKET_SPLIT
- uint32_t pages = 0;
-#endif
rctl = E1000_READ_REG(&adapter->hw, RCTL);
@@ -1519,7 +1235,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- if(adapter->hw.mac_type >= e1000_82571) {
+ if(adapter->hw.mac_type == e1000_82573) {
/* We can now specify buffers in 1K increments.
* BSIZE and BSEX are ignored in this case. */
rctl |= adapter->rx_buffer_len << 0x11;
@@ -1552,14 +1268,11 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
* followed by the page buffers. Therefore, skb->data is
* sized to hold the largest protocol header.
*/
- pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- if ((adapter->hw.mac_type > e1000_82547_rev_2) && (pages <= 3) &&
- PAGE_SIZE <= 16384)
- adapter->rx_ps_pages = pages;
- else
- adapter->rx_ps_pages = 0;
+ adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2)
+ && (adapter->netdev->mtu
+ < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
#endif
- if (adapter->rx_ps_pages) {
+ if(adapter->rx_ps) {
/* Configure extra packet-split registers */
rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
@@ -1571,19 +1284,12 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
-
- switch (adapter->rx_ps_pages) {
- case 3:
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE3_SHIFT;
- case 2:
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE2_SHIFT;
- case 1:
- psrctl |= PAGE_SIZE >>
- E1000_PSRCTL_BSIZE1_SHIFT;
- break;
- }
+ psrctl |= PAGE_SIZE >>
+ E1000_PSRCTL_BSIZE1_SHIFT;
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE2_SHIFT;
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE3_SHIFT;
E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
}
@@ -1601,181 +1307,91 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
static void
e1000_configure_rx(struct e1000_adapter *adapter)
{
- uint64_t rdba;
- struct e1000_hw *hw = &adapter->hw;
- uint32_t rdlen, rctl, rxcsum, ctrl_ext;
-#ifdef CONFIG_E1000_MQ
- uint32_t reta, mrqc;
- int i;
-#endif
+ uint64_t rdba = adapter->rx_ring.dma;
+ uint32_t rdlen, rctl, rxcsum;
- if (adapter->rx_ps_pages) {
- rdlen = adapter->rx_ring[0].count *
+ if(adapter->rx_ps) {
+ rdlen = adapter->rx_ring.count *
sizeof(union e1000_rx_desc_packet_split);
adapter->clean_rx = e1000_clean_rx_irq_ps;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
} else {
- rdlen = adapter->rx_ring[0].count *
- sizeof(struct e1000_rx_desc);
+ rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
adapter->clean_rx = e1000_clean_rx_irq;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
}
/* disable receives while setting up the descriptors */
- rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
/* set the Receive Delay Timer Register */
- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+ E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
- if (hw->mac_type >= e1000_82540) {
- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
+ if(adapter->hw.mac_type >= e1000_82540) {
+ E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
if(adapter->itr > 1)
- E1000_WRITE_REG(hw, ITR,
+ E1000_WRITE_REG(&adapter->hw, ITR,
1000000000 / (adapter->itr * 256));
}
- if (hw->mac_type >= e1000_82571) {
- /* Reset delay timers after every interrupt */
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_CANC;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
- }
-
- /* Setup the HW Rx Head and Tail Descriptor Pointers and
- * the Base and Length of the Rx Descriptor Ring */
- switch (adapter->num_queues) {
-#ifdef CONFIG_E1000_MQ
- case 2:
- rdba = adapter->rx_ring[1].dma;
- E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32));
- E1000_WRITE_REG(hw, RDLEN1, rdlen);
- E1000_WRITE_REG(hw, RDH1, 0);
- E1000_WRITE_REG(hw, RDT1, 0);
- adapter->rx_ring[1].rdh = E1000_RDH1;
- adapter->rx_ring[1].rdt = E1000_RDT1;
- /* Fall Through */
-#endif
- case 1:
- default:
- rdba = adapter->rx_ring[0].dma;
- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
- E1000_WRITE_REG(hw, RDLEN, rdlen);
- E1000_WRITE_REG(hw, RDH, 0);
- E1000_WRITE_REG(hw, RDT, 0);
- adapter->rx_ring[0].rdh = E1000_RDH;
- adapter->rx_ring[0].rdt = E1000_RDT;
- break;
- }
-
-#ifdef CONFIG_E1000_MQ
- if (adapter->num_queues > 1) {
- uint32_t random[10];
-
- get_random_bytes(&random[0], 40);
-
- if (hw->mac_type <= e1000_82572) {
- E1000_WRITE_REG(hw, RSSIR, 0);
- E1000_WRITE_REG(hw, RSSIM, 0);
- }
-
- switch (adapter->num_queues) {
- case 2:
- default:
- reta = 0x00800080;
- mrqc = E1000_MRQC_ENABLE_RSS_2Q;
- break;
- }
-
- /* Fill out redirection table */
- for (i = 0; i < 32; i++)
- E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
- /* Fill out hash function seeds */
- for (i = 0; i < 10; i++)
- E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
-
- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
- E1000_MRQC_RSS_FIELD_IPV4_TCP);
- E1000_WRITE_REG(hw, MRQC, mrqc);
- }
+ /* Setup the Base and Length of the Rx Descriptor Ring */
+ E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
- /* Multiqueue and packet checksumming are mutually exclusive. */
- if (hw->mac_type >= e1000_82571) {
- rxcsum = E1000_READ_REG(hw, RXCSUM);
- rxcsum |= E1000_RXCSUM_PCSD;
- E1000_WRITE_REG(hw, RXCSUM, rxcsum);
- }
+ E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
-#else
+ /* Setup the HW Rx Head and Tail Descriptor Pointers */
+ E1000_WRITE_REG(&adapter->hw, RDH, 0);
+ E1000_WRITE_REG(&adapter->hw, RDT, 0);
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
- if (hw->mac_type >= e1000_82543) {
- rxcsum = E1000_READ_REG(hw, RXCSUM);
+ if(adapter->hw.mac_type >= e1000_82543) {
+ rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
if(adapter->rx_csum == TRUE) {
rxcsum |= E1000_RXCSUM_TUOFL;
- /* Enable 82571 IPv4 payload checksum for UDP fragments
+ /* Enable 82573 IPv4 payload checksum for UDP fragments
* Must be used in conjunction with packet-split. */
- if ((hw->mac_type >= e1000_82571) &&
- (adapter->rx_ps_pages)) {
+ if((adapter->hw.mac_type > e1000_82547_rev_2) &&
+ (adapter->rx_ps)) {
rxcsum |= E1000_RXCSUM_IPPCSE;
}
} else {
rxcsum &= ~E1000_RXCSUM_TUOFL;
/* don't need to clear IPPCSE as it defaults to 0 */
}
- E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+ E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
}
-#endif /* CONFIG_E1000_MQ */
- if (hw->mac_type == e1000_82573)
- E1000_WRITE_REG(hw, ERT, 0x0100);
+ if (adapter->hw.mac_type == e1000_82573)
+ E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
/* Enable Receives */
- E1000_WRITE_REG(hw, RCTL, rctl);
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
/**
- * e1000_free_tx_resources - Free Tx Resources per Queue
+ * e1000_free_tx_resources - Free Tx Resources
* @adapter: board private structure
- * @tx_ring: Tx descriptor ring for a specific queue
*
* Free all transmit software resources
**/
void
-e1000_free_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+e1000_free_tx_resources(struct e1000_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
- e1000_clean_tx_ring(adapter, tx_ring);
-
- vfree(tx_ring->buffer_info);
- tx_ring->buffer_info = NULL;
+ e1000_clean_tx_ring(adapter);
- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
-
- tx_ring->desc = NULL;
-}
+ vfree(adapter->tx_ring.buffer_info);
+ adapter->tx_ring.buffer_info = NULL;
-/**
- * e1000_free_all_tx_resources - Free Tx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all transmit software resources
- **/
-
-void
-e1000_free_all_tx_resources(struct e1000_adapter *adapter)
-{
- int i;
+ pci_free_consistent(pdev, adapter->tx_ring.size,
+ adapter->tx_ring.desc, adapter->tx_ring.dma);
- for (i = 0; i < adapter->num_queues; i++)
- e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
+ adapter->tx_ring.desc = NULL;
}
static inline void
@@ -1798,22 +1414,21 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
/**
* e1000_clean_tx_ring - Free Tx Buffers
* @adapter: board private structure
- * @tx_ring: ring to be cleaned
**/
static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+e1000_clean_tx_ring(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
unsigned long size;
unsigned int i;
/* Free all the Tx ring sk_buffs */
- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
+ if (likely(adapter->previous_buffer_info.skb != NULL)) {
e1000_unmap_and_free_tx_resource(adapter,
- &tx_ring->previous_buffer_info);
+ &adapter->previous_buffer_info);
}
for(i = 0; i < tx_ring->count; i++) {
@@ -1831,39 +1446,24 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- writel(0, adapter->hw.hw_addr + tx_ring->tdh);
- writel(0, adapter->hw.hw_addr + tx_ring->tdt);
-}
-
-/**
- * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
- * @adapter: board private structure
- **/
-
-static void
-e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
-{
- int i;
-
- for (i = 0; i < adapter->num_queues; i++)
- e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
+ E1000_WRITE_REG(&adapter->hw, TDH, 0);
+ E1000_WRITE_REG(&adapter->hw, TDT, 0);
}
/**
* e1000_free_rx_resources - Free Rx Resources
* @adapter: board private structure
- * @rx_ring: ring to clean the resources from
*
* Free all receive software resources
**/
void
-e1000_free_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+e1000_free_rx_resources(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
- e1000_clean_rx_ring(adapter, rx_ring);
+ e1000_clean_rx_ring(adapter);
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
@@ -1878,31 +1478,14 @@ e1000_free_rx_resources(struct e1000_adapter *adapter,
}
/**
- * e1000_free_all_rx_resources - Free Rx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all receive software resources
- **/
-
-void
-e1000_free_all_rx_resources(struct e1000_adapter *adapter)
-{
- int i;
-
- for (i = 0; i < adapter->num_queues; i++)
- e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
-}
-
-/**
- * e1000_clean_rx_ring - Free Rx Buffers per Queue
+ * e1000_clean_rx_ring - Free Rx Buffers
* @adapter: board private structure
- * @rx_ring: ring to free buffers from
**/
static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+e1000_clean_rx_ring(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
@@ -1925,7 +1508,7 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
- for(j = 0; j < adapter->rx_ps_pages; j++) {
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
if(!ps_page->ps_page[j]) break;
pci_unmap_single(pdev,
ps_page_dma->ps_page_dma[j],
@@ -1951,22 +1534,8 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- writel(0, adapter->hw.hw_addr + rx_ring->rdh);
- writel(0, adapter->hw.hw_addr + rx_ring->rdt);
-}
-
-/**
- * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
- * @adapter: board private structure
- **/
-
-static void
-e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
-{
- int i;
-
- for (i = 0; i < adapter->num_queues; i++)
- e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
+ E1000_WRITE_REG(&adapter->hw, RDH, 0);
+ E1000_WRITE_REG(&adapter->hw, RDT, 0);
}
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
@@ -1987,7 +1556,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
mdelay(5);
if(netif_running(netdev))
- e1000_clean_all_rx_rings(adapter);
+ e1000_clean_rx_ring(adapter);
}
static void
@@ -2007,7 +1576,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
if(netif_running(netdev)) {
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
+ e1000_alloc_rx_buffers(adapter);
}
}
@@ -2038,22 +1607,6 @@ e1000_set_mac(struct net_device *netdev, void *p)
e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
- /* With 82571 controllers, LAA may be overwritten (with the default)
- * due to controller reset from the other port. */
- if (adapter->hw.mac_type == e1000_82571) {
- /* activate the work around */
- adapter->hw.laa_is_present = 1;
-
- /* Hold a copy of the LAA in RAR[14] This is done so that
- * between the time RAR[0] gets clobbered and the time it
- * gets fixed (in e1000_watchdog), the actual LAA is in one
- * of the RARs and no incoming packets directed to this port
- * are dropped. Eventaully the LAA will be in RAR[0] and
- * RAR[14] */
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
- E1000_RAR_ENTRIES - 1);
- }
-
if(adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
@@ -2076,13 +1629,12 @@ e1000_set_multi(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
+ unsigned long flags;
uint32_t rctl;
uint32_t hash_value;
- int i, rar_entries = E1000_RAR_ENTRIES;
+ int i;
- /* reserve RAR[14] for LAA over-write work-around */
- if (adapter->hw.mac_type == e1000_82571)
- rar_entries--;
+ spin_lock_irqsave(&adapter->tx_lock, flags);
/* Check for Promiscuous and All Multicast modes */
@@ -2107,12 +1659,11 @@ e1000_set_multi(struct net_device *netdev)
/* load the first 14 multicast address into the exact filters 1-14
* RAR 0 is used for the station MAC adddress
* if there are not 14 addresses, go ahead and clear the filters
- * -- with 82571 controllers only 0-13 entries are filled here
*/
mc_ptr = netdev->mc_list;
- for(i = 1; i < rar_entries; i++) {
- if (mc_ptr) {
+ for(i = 1; i < E1000_RAR_ENTRIES; i++) {
+ if(mc_ptr) {
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
mc_ptr = mc_ptr->next;
} else {
@@ -2135,6 +1686,8 @@ e1000_set_multi(struct net_device *netdev)
if(hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
+
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
}
/* Need to wait a few seconds after link up to get diagnostic information from
@@ -2206,7 +1759,7 @@ static void
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
+ struct e1000_desc_ring *txdr = &adapter->tx_ring;
uint32_t link;
e1000_check_for_link(&adapter->hw);
@@ -2265,8 +1818,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
e1000_update_adaptive(&adapter->hw);
- if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
- if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
+ if(!netif_carrier_ok(netdev)) {
+ if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
@@ -2294,11 +1847,6 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = TRUE;
- /* With 82571 controllers, LAA may be overwritten due to controller
- * reset from the other port. Set the appropriate LAA in RAR[0] */
- if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
-
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
@@ -2311,8 +1859,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
#define E1000_TX_FLAGS_VLAN_SHIFT 16
static inline int
-e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb)
+e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
@@ -2363,8 +1910,8 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
- i = tx_ring->next_to_use;
- context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ i = adapter->tx_ring.next_to_use;
+ context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
@@ -2376,8 +1923,8 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
- if (++i == tx_ring->count) i = 0;
- tx_ring->next_to_use = i;
+ if(++i == adapter->tx_ring.count) i = 0;
+ adapter->tx_ring.next_to_use = i;
return 1;
}
@@ -2387,8 +1934,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
}
static inline boolean_t
-e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb)
+e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
unsigned int i;
@@ -2397,8 +1943,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
if(likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
- i = tx_ring->next_to_use;
- context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ i = adapter->tx_ring.next_to_use;
+ context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
@@ -2406,8 +1952,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
- if (unlikely(++i == tx_ring->count)) i = 0;
- tx_ring->next_to_use = i;
+ if(unlikely(++i == adapter->tx_ring.count)) i = 0;
+ adapter->tx_ring.next_to_use = i;
return TRUE;
}
@@ -2419,10 +1965,11 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
#define E1000_MAX_DATA_PER_TXD (1<tx_ring;
struct e1000_buffer *buffer_info;
unsigned int len = skb->len;
unsigned int offset = 0, size, count = 0, i;
@@ -2518,9 +2065,9 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
}
static inline void
-e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- int tx_flags, int count)
+e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
{
+ struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_tx_desc *tx_desc = NULL;
struct e1000_buffer *buffer_info;
uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -2566,7 +2113,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
wmb();
tx_ring->next_to_use = i;
- writel(i, adapter->hw.hw_addr + tx_ring->tdt);
+ E1000_WRITE_REG(&adapter->hw, TDT, i);
}
/**
@@ -2659,7 +2206,6 @@ static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_tx_ring *tx_ring;
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
unsigned int tx_flags = 0;
@@ -2672,13 +2218,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int f;
len -= skb->data_len;
-#ifdef CONFIG_E1000_MQ
- tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
-#else
- tx_ring = adapter->tx_ring;
-#endif
-
- if (unlikely(skb->len <= 0)) {
+ if(unlikely(skb->len <= 0)) {
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2722,42 +2262,21 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(adapter->pcix_82544)
count += nr_frags;
-#ifdef NETIF_F_TSO
- /* TSO Workaround for 82571/2 Controllers -- if skb->data
- * points to just header, pull a few bytes of payload from
- * frags into skb->data */
- if (skb_shinfo(skb)->tso_size) {
- uint8_t hdr_len;
- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) &&
- (adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572)) {
- unsigned int pull_size;
- pull_size = min((unsigned int)4, skb->data_len);
- if (!__pskb_pull_tail(skb, pull_size)) {
- printk(KERN_ERR "__pskb_pull_tail failed.\n");
- dev_kfree_skb_any(skb);
- return -EFAULT;
- }
- }
- }
-#endif
-
+ local_irq_save(flags);
+ if (!spin_trylock(&adapter->tx_lock)) {
+ /* Collision - tell upper layer to requeue */
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
- local_irq_save(flags);
- if (!spin_trylock(&tx_ring->tx_lock)) {
- /* Collision - tell upper layer to requeue */
- local_irq_restore(flags);
- return NETDEV_TX_LOCKED;
- }
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
- if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 2)) {
+ if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2)) {
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_BUSY;
}
@@ -2765,7 +2284,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_BUSY;
}
}
@@ -2775,37 +2294,37 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
- first = tx_ring->next_to_use;
+ first = adapter->tx_ring.next_to_use;
- tso = e1000_tso(adapter, tx_ring, skb);
+ tso = e1000_tso(adapter, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_OK;
}
if (likely(tso))
tx_flags |= E1000_TX_FLAGS_TSO;
- else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+ else if(likely(e1000_tx_csum(adapter, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
/* Old method was to assume IPv4 packet by default if TSO was enabled.
- * 82571 hardware supports TSO capabilities for IPv6 as well...
+ * 82573 hardware supports TSO capabilities for IPv6 as well...
* no longer assume, we must. */
- if (likely(skb->protocol == ntohs(ETH_P_IP)))
+ if(likely(skb->protocol == ntohs(ETH_P_IP)))
tx_flags |= E1000_TX_FLAGS_IPV4;
- e1000_tx_queue(adapter, tx_ring, tx_flags,
- e1000_tx_map(adapter, tx_ring, skb, first,
- max_per_txd, nr_frags, mss));
+ e1000_tx_queue(adapter,
+ e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
+ tx_flags);
netdev->trans_start = jiffies;
/* Make sure there is space in the ring for the next send. */
- if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
+ if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < MAX_SKB_FRAGS + 2))
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_OK;
}
@@ -2869,18 +2388,9 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
+#define MAX_STD_JUMBO_FRAME_SIZE 9216
/* might want this to be bigger enum check... */
- /* 82571 controllers limit jumbo frame size to 10500 bytes */
- if ((adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572) &&
- max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
- DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
- "on 82571 and 82572 controllers.\n");
- return -EINVAL;
- }
-
- if(adapter->hw.mac_type == e1000_82573 &&
+ if (adapter->hw.mac_type == e1000_82573 &&
max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
"on 82573\n");
@@ -3068,29 +2578,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
-#ifdef CONFIG_E1000_MQ
-void
-e1000_rx_schedule(void *data)
-{
- struct net_device *poll_dev, *netdev = data;
- struct e1000_adapter *adapter = netdev->priv;
- int this_cpu = get_cpu();
-
- poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
- if (poll_dev == NULL) {
- put_cpu();
- return;
- }
-
- if (likely(netif_rx_schedule_prep(poll_dev)))
- __netif_rx_schedule(poll_dev);
- else
- e1000_irq_enable(adapter);
-
- put_cpu();
-}
-#endif
-
/**
* e1000_intr - Interrupt Handler
* @irq: interrupt number
@@ -3105,8 +2592,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
uint32_t icr = E1000_READ_REG(hw, ICR);
-#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
- int i;
+#ifndef CONFIG_E1000_NAPI
+ unsigned int i;
#endif
if(unlikely(!icr))
@@ -3118,31 +2605,17 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
#ifdef CONFIG_E1000_NAPI
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(hw, IMC, ~0);
- E1000_WRITE_FLUSH(hw);
-#ifdef CONFIG_E1000_MQ
- if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
- cpu_set(adapter->cpu_for_queue[0],
- adapter->rx_sched_call_data.cpumask);
- for (i = 1; i < adapter->num_queues; i++) {
- cpu_set(adapter->cpu_for_queue[i],
- adapter->rx_sched_call_data.cpumask);
- atomic_inc(&adapter->irq_sem);
- }
- atomic_set(&adapter->rx_sched_call_data.count, i);
- smp_call_async_mask(&adapter->rx_sched_call_data);
- } else {
- printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
- }
-#else /* if !CONFIG_E1000_MQ */
- if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
- __netif_rx_schedule(&adapter->polling_netdev[0]);
- else
- e1000_irq_enable(adapter);
-#endif /* CONFIG_E1000_MQ */
+ if(likely(netif_rx_schedule_prep(netdev))) {
+
+ /* Disable interrupts and register for poll. The flush
+ of the posted write is intentionally left out.
+ */
-#else /* if !CONFIG_E1000_NAPI */
+ atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(hw, IMC, ~0);
+ __netif_rx_schedule(netdev);
+ }
+#else
/* Writing IMC and IMS is needed for 82547.
Due to Hub Link bus being occupied, an interrupt
de-assertion message is not able to be sent.
@@ -3159,14 +2632,13 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
- !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
+ if(unlikely(!adapter->clean_rx(adapter) &
+ !e1000_clean_tx_irq(adapter)))
break;
if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
-
-#endif /* CONFIG_E1000_NAPI */
+#endif
return IRQ_HANDLED;
}
@@ -3178,37 +2650,22 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
**/
static int
-e1000_clean(struct net_device *poll_dev, int *budget)
+e1000_clean(struct net_device *netdev, int *budget)
{
- struct e1000_adapter *adapter;
- int work_to_do = min(*budget, poll_dev->quota);
- int tx_cleaned, i = 0, work_done = 0;
-
- /* Must NOT use netdev_priv macro here. */
- adapter = poll_dev->priv;
-
- /* Keep link state information with original netdev */
- if (!netif_carrier_ok(adapter->netdev))
- goto quit_polling;
-
- while (poll_dev != &adapter->polling_netdev[i]) {
- i++;
- if (unlikely(i == adapter->num_queues))
- BUG();
- }
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ int work_to_do = min(*budget, netdev->quota);
+ int tx_cleaned;
+ int work_done = 0;
- tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
- adapter->clean_rx(adapter, &adapter->rx_ring[i],
- &work_done, work_to_do);
+ tx_cleaned = e1000_clean_tx_irq(adapter);
+ adapter->clean_rx(adapter, &work_done, work_to_do);
*budget -= work_done;
- poll_dev->quota -= work_done;
+ netdev->quota -= work_done;
+ if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
/* If no Tx and not enough Rx work done, exit the polling mode */
- if((!tx_cleaned && (work_done == 0)) ||
- !netif_running(adapter->netdev)) {
-quit_polling:
- netif_rx_complete(poll_dev);
+ netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
}
@@ -3223,9 +2680,9 @@ e1000_clean(struct net_device *poll_dev, int *budget)
**/
static boolean_t
-e1000_clean_tx_irq(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+e1000_clean_tx_irq(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
@@ -3236,12 +2693,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
- while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+ while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
/* Premature writeback of Tx descriptors clear (free buffers
* and unmap pci_mapping) previous_buffer_info */
- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
+ if (likely(adapter->previous_buffer_info.skb != NULL)) {
e1000_unmap_and_free_tx_resource(adapter,
- &tx_ring->previous_buffer_info);
+ &adapter->previous_buffer_info);
}
for(cleaned = FALSE; !cleaned; ) {
@@ -3257,7 +2714,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
#ifdef NETIF_F_TSO
} else {
if (cleaned) {
- memcpy(&tx_ring->previous_buffer_info,
+ memcpy(&adapter->previous_buffer_info,
buffer_info,
sizeof(struct e1000_buffer));
memset(buffer_info, 0,
@@ -3275,8 +2732,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
if(unlikely(++i == tx_ring->count)) i = 0;
}
-
- tx_ring->pkt++;
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
@@ -3284,15 +2739,15 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
tx_ring->next_to_clean = i;
- spin_lock(&tx_ring->tx_lock);
+ spin_lock(&adapter->tx_lock);
if(unlikely(cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev)))
netif_wake_queue(netdev);
- spin_unlock(&tx_ring->tx_lock);
+ spin_unlock(&adapter->tx_lock);
+ if(adapter->detect_tx_hung) {
- if (adapter->detect_tx_hung) {
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
adapter->detect_tx_hung = FALSE;
@@ -3316,8 +2771,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
- readl(adapter->hw.hw_addr + tx_ring->tdh),
- readl(adapter->hw.hw_addr + tx_ring->tdt),
+ E1000_READ_REG(&adapter->hw, TDH),
+ E1000_READ_REG(&adapter->hw, TDT),
tx_ring->next_to_use,
i,
(unsigned long long)tx_ring->buffer_info[i].dma,
@@ -3329,10 +2784,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
}
}
#ifdef NETIF_F_TSO
- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
+
+ if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+ time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ)))
e1000_unmap_and_free_tx_resource(
- adapter, &tx_ring->previous_buffer_info);
+ adapter, &adapter->previous_buffer_info);
+
#endif
return cleaned;
}
@@ -3395,14 +2852,13 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
static boolean_t
#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
+e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
+ int work_to_do)
#else
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+e1000_clean_rx_irq(struct e1000_adapter *adapter)
#endif
{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -3488,7 +2944,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
next_desc:
rx_desc->status = 0;
@@ -3498,7 +2953,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+ adapter->alloc_rx_buf(adapter);
return cleaned;
}
@@ -3510,14 +2965,13 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
static boolean_t
#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
+ int work_to_do)
#else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
#endif
{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
union e1000_rx_desc_packet_split *rx_desc;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3573,7 +3027,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
/* Good Receive */
skb_put(skb, length);
- for(j = 0; j < adapter->rx_ps_pages; j++) {
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
@@ -3594,13 +3048,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
skb->protocol = eth_type_trans(skb, netdev);
- if(likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP)) {
- adapter->rx_hdr_split++;
#ifdef HAVE_RX_ZERO_COPY
+ if(likely(rx_desc->wb.upper.header_status &
+ E1000_RXDPS_HDRSTAT_HDRSP))
skb_shinfo(skb)->zero_copy = TRUE;
#endif
- }
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -3619,7 +3071,6 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;
@@ -3630,7 +3081,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+ adapter->alloc_rx_buf(adapter);
return cleaned;
}
@@ -3641,9 +3092,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
**/
static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -3727,7 +3178,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ E1000_WRITE_REG(&adapter->hw, RDT, i);
}
if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3743,9 +3194,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
**/
static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_packet_split *rx_desc;
@@ -3764,26 +3215,22 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
for(j = 0; j < PS_PAGE_BUFFERS; j++) {
- if (j < adapter->rx_ps_pages) {
- if (likely(!ps_page->ps_page[j])) {
- ps_page->ps_page[j] =
- alloc_page(GFP_ATOMIC);
- if (unlikely(!ps_page->ps_page[j]))
- goto no_buffers;
- ps_page_dma->ps_page_dma[j] =
- pci_map_page(pdev,
- ps_page->ps_page[j],
- 0, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- }
- /* Refresh the desc even if buffer_addrs didn't
- * change because each write-back erases
- * this info.
- */
- rx_desc->read.buffer_addr[j+1] =
- cpu_to_le64(ps_page_dma->ps_page_dma[j]);
- } else
- rx_desc->read.buffer_addr[j+1] = ~0;
+ if(unlikely(!ps_page->ps_page[j])) {
+ ps_page->ps_page[j] =
+ alloc_page(GFP_ATOMIC);
+ if(unlikely(!ps_page->ps_page[j]))
+ goto no_buffers;
+ ps_page_dma->ps_page_dma[j] =
+ pci_map_page(pdev,
+ ps_page->ps_page[j],
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ }
+ /* Refresh the desc even if buffer_addrs didn't
+ * change because each write-back erases this info.
+ */
+ rx_desc->read.buffer_addr[j+1] =
+ cpu_to_le64(ps_page_dma->ps_page_dma[j]);
}
skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
@@ -3817,7 +3264,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
* descriptors are 32 bytes...so we increment tail
* twice as much.
*/
- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+ E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
}
if(unlikely(++i == rx_ring->count)) i = 0;
@@ -4268,12 +3715,6 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
}
switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -4296,7 +3737,6 @@ e1000_resume(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t manc, ret_val, swsm;
- uint32_t ctrl_ext;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
@@ -4322,12 +3762,6 @@ e1000_resume(struct pci_dev *pdev)
}
switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -4352,7 +3786,7 @@ e1000_netpoll(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
- e1000_clean_tx_irq(adapter, adapter->tx_ring);
+ e1000_clean_tx_irq(adapter);
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/trunk/drivers/net/e1000/e1000_param.c b/trunk/drivers/net/e1000/e1000_param.c
index 38695d5b4637..676247f9f1cc 100644
--- a/trunk/drivers/net/e1000/e1000_param.c
+++ b/trunk/drivers/net/e1000/e1000_param.c
@@ -306,8 +306,7 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = E1000_DEFAULT_TXD,
.arg = { .r = { .min = E1000_MIN_TXD }}
};
- struct e1000_tx_ring *tx_ring = adapter->tx_ring;
- int i;
+ struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
e1000_mac_type mac_type = adapter->hw.mac_type;
opt.arg.r.max = mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD;
@@ -320,8 +319,6 @@ e1000_check_options(struct e1000_adapter *adapter)
} else {
tx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
- tx_ring[i].count = tx_ring->count;
}
{ /* Receive Descriptor Count */
struct e1000_option opt = {
@@ -332,8 +329,7 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = E1000_DEFAULT_RXD,
.arg = { .r = { .min = E1000_MIN_RXD }}
};
- struct e1000_rx_ring *rx_ring = adapter->rx_ring;
- int i;
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
e1000_mac_type mac_type = adapter->hw.mac_type;
opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
@@ -346,8 +342,6 @@ e1000_check_options(struct e1000_adapter *adapter)
} else {
rx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
- rx_ring[i].count = rx_ring->count;
}
{ /* Checksum Offload Enable/Disable */
struct e1000_option opt = {
diff --git a/trunk/drivers/net/epic100.c b/trunk/drivers/net/epic100.c
index f119ec4e89ea..87f522738bfc 100644
--- a/trunk/drivers/net/epic100.c
+++ b/trunk/drivers/net/epic100.c
@@ -1334,7 +1334,7 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
static int epic_poll(struct net_device *dev, int *budget)
{
struct epic_private *ep = dev->priv;
- int work_done = 0, orig_budget;
+ int work_done, orig_budget;
long ioaddr = dev->base_addr;
orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
@@ -1343,7 +1343,7 @@ static int epic_poll(struct net_device *dev, int *budget)
epic_tx(dev, ep);
- work_done += epic_rx(dev, *budget);
+ work_done = epic_rx(dev, *budget);
epic_rx_err(dev, ep);
diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c
index 22aec6ed80f5..d6eefdb71c17 100644
--- a/trunk/drivers/net/forcedeth.c
+++ b/trunk/drivers/net/forcedeth.c
@@ -95,8 +95,6 @@
* of nv_remove
* 0.42: 06 Aug 2005: Fix lack of link speed initialization
* in the second (and later) nv_open call
- * 0.43: 10 Aug 2005: Add support for tx checksum.
- * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -108,7 +106,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.44"
+#define FORCEDETH_VERSION "0.41"
#define DRV_NAME "forcedeth"
#include
@@ -147,7 +145,6 @@
#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
-#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */
enum {
NvRegIrqStatus = 0x000,
@@ -244,9 +241,6 @@ enum {
#define NVREG_TXRXCTL_IDLE 0x0008
#define NVREG_TXRXCTL_RESET 0x0010
#define NVREG_TXRXCTL_RXCHECK 0x0400
-#define NVREG_TXRXCTL_DESC_1 0
-#define NVREG_TXRXCTL_DESC_2 0x02100
-#define NVREG_TXRXCTL_DESC_3 0x02200
NvRegMIIStatus = 0x180,
#define NVREG_MIISTAT_ERROR 0x0001
#define NVREG_MIISTAT_LINKCHANGE 0x0008
@@ -341,10 +335,6 @@ typedef union _ring_type {
/* error and valid are the same for both */
#define NV_TX2_ERROR (1<<30)
#define NV_TX2_VALID (1<<31)
-#define NV_TX2_TSO (1<<28)
-#define NV_TX2_TSO_SHIFT 14
-#define NV_TX2_CHECKSUM_L3 (1<<27)
-#define NV_TX2_CHECKSUM_L4 (1<<26)
#define NV_RX_DESCRIPTORVALID (1<<16)
#define NV_RX_MISSEDFRAME (1<<17)
@@ -427,14 +417,14 @@ typedef union _ring_type {
/*
* desc_ver values:
- * The nic supports three different descriptor types:
- * - DESC_VER_1: Original
- * - DESC_VER_2: support for jumbo frames.
- * - DESC_VER_3: 64-bit format.
+ * This field has two purposes:
+ * - Newer nics uses a different ring layout. The layout is selected by
+ * comparing np->desc_ver with DESC_VER_xy.
+ * - It contains bits that are forced on when writing to NvRegTxRxControl.
*/
-#define DESC_VER_1 1
-#define DESC_VER_2 2
-#define DESC_VER_3 3
+#define DESC_VER_1 0x0
+#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_3 (0x02200|NVREG_TXRXCTL_RXCHECK)
/* PHY defines */
#define PHY_OUI_MARVELL 0x5043
@@ -501,7 +491,6 @@ struct fe_priv {
u32 orig_mac[2];
u32 irqmask;
u32 desc_ver;
- u32 txrxctl_bits;
void __iomem *base;
@@ -545,7 +534,7 @@ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
static inline u8 __iomem *get_hwbase(struct net_device *dev)
{
- return ((struct fe_priv *)netdev_priv(dev))->base;
+ return get_nvpriv(dev)->base;
}
static inline void pci_push(u8 __iomem *base)
@@ -634,7 +623,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
static int phy_reset(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u32 miicontrol;
unsigned int tries = 0;
@@ -737,7 +726,7 @@ static int phy_init(struct net_device *dev)
static void nv_start_rx(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
@@ -793,14 +782,14 @@ static void nv_stop_tx(struct net_device *dev)
static void nv_txrx_reset(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
- writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
pci_push(base);
udelay(NV_TXRX_RESET_DELAY);
- writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
pci_push(base);
}
@@ -812,7 +801,7 @@ static void nv_txrx_reset(struct net_device *dev)
*/
static struct net_device_stats *nv_get_stats(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
/* It seems that the nic always generates interrupts and doesn't
* accumulate errors internally. Thus the current values in np->stats
@@ -828,7 +817,7 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
*/
static int nv_alloc_rx(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
unsigned int refill_rx = np->refill_rx;
int nr;
@@ -872,7 +861,7 @@ static int nv_alloc_rx(struct net_device *dev)
static void nv_do_rx_refill(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
disable_irq(dev->irq);
if (nv_alloc_rx(dev)) {
@@ -886,7 +875,7 @@ static void nv_do_rx_refill(unsigned long data)
static void nv_init_rx(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
int i;
np->cur_rx = RX_RING;
@@ -900,17 +889,15 @@ static void nv_init_rx(struct net_device *dev)
static void nv_init_tx(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
int i;
np->next_tx = np->nic_tx = 0;
- for (i = 0; i < TX_RING; i++) {
+ for (i = 0; i < TX_RING; i++)
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
np->tx_ring.orig[i].FlagLen = 0;
else
np->tx_ring.ex[i].FlagLen = 0;
- np->tx_skbuff[i] = NULL;
- }
}
static int nv_init_ring(struct net_device *dev)
@@ -920,44 +907,21 @@ static int nv_init_ring(struct net_device *dev)
return nv_alloc_rx(dev);
}
-static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
-{
- struct fe_priv *np = netdev_priv(dev);
- struct sk_buff *skb = np->tx_skbuff[skbnr];
- unsigned int j, entry, fragments;
-
- dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
- dev->name, skbnr, np->tx_skbuff[skbnr]);
-
- entry = skbnr;
- if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
- for (j = fragments; j >= 1; j--) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
- pci_unmap_page(np->pci_dev, np->tx_dma[entry],
- frag->size,
- PCI_DMA_TODEVICE);
- entry = (entry - 1) % TX_RING;
- }
- }
- pci_unmap_single(np->pci_dev, np->tx_dma[entry],
- skb->len - skb->data_len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
- np->tx_skbuff[skbnr] = NULL;
-}
-
static void nv_drain_tx(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
- unsigned int i;
-
+ struct fe_priv *np = get_nvpriv(dev);
+ int i;
for (i = 0; i < TX_RING; i++) {
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
np->tx_ring.orig[i].FlagLen = 0;
else
np->tx_ring.ex[i].FlagLen = 0;
if (np->tx_skbuff[i]) {
- nv_release_txskb(dev, i);
+ pci_unmap_single(np->pci_dev, np->tx_dma[i],
+ np->tx_skbuff[i]->len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb(np->tx_skbuff[i]);
+ np->tx_skbuff[i] = NULL;
np->stats.tx_dropped++;
}
}
@@ -965,7 +929,7 @@ static void nv_drain_tx(struct net_device *dev)
static void nv_drain_rx(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
int i;
for (i = 0; i < RX_RING; i++) {
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
@@ -995,69 +959,28 @@ static void drain_ring(struct net_device *dev)
*/
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
- u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
- unsigned int fragments = skb_shinfo(skb)->nr_frags;
- unsigned int nr = (np->next_tx + fragments) % TX_RING;
- unsigned int i;
-
- spin_lock_irq(&np->lock);
-
- if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
- spin_unlock_irq(&np->lock);
- netif_stop_queue(dev);
- return NETDEV_TX_BUSY;
- }
+ struct fe_priv *np = get_nvpriv(dev);
+ int nr = np->next_tx % TX_RING;
np->tx_skbuff[nr] = skb;
-
- if (fragments) {
- dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
- /* setup descriptors in reverse order */
- for (i = fragments; i >= 1; i--) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
- np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
-
- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
- np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
- np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
- } else {
- np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
- np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
- np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
- }
-
- nr = (nr - 1) % TX_RING;
-
- if (np->desc_ver == DESC_VER_1)
- tx_flags_extra &= ~NV_TX_LASTPACKET;
- else
- tx_flags_extra &= ~NV_TX2_LASTPACKET;
- }
- }
-
-#ifdef NETIF_F_TSO
- if (skb_shinfo(skb)->tso_size)
- tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
- else
-#endif
- tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
-
- np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
+ np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
PCI_DMA_TODEVICE);
-
- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
- np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
- } else {
+ else {
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
- np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
- }
+ }
- dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
- dev->name, np->next_tx, tx_flags_extra);
+ spin_lock_irq(&np->lock);
+ wmb();
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+ else
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
+ dev->name, np->next_tx);
{
int j;
for (j=0; j<64; j++) {
@@ -1068,13 +991,15 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
dprintk("\n");
}
- np->next_tx += 1 + fragments;
+ np->next_tx++;
dev->trans_start = jiffies;
+ if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
+ netif_stop_queue(dev);
spin_unlock_irq(&np->lock);
- writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
pci_push(get_hwbase(dev));
- return NETDEV_TX_OK;
+ return 0;
}
/*
@@ -1084,10 +1009,9 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static void nv_tx_done(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u32 Flags;
- unsigned int i;
- struct sk_buff *skb;
+ int i;
while (np->nic_tx != np->next_tx) {
i = np->nic_tx % TX_RING;
@@ -1102,38 +1026,35 @@ static void nv_tx_done(struct net_device *dev)
if (Flags & NV_TX_VALID)
break;
if (np->desc_ver == DESC_VER_1) {
- if (Flags & NV_TX_LASTPACKET) {
- skb = np->tx_skbuff[i];
- if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
- NV_TX_UNDERFLOW|NV_TX_ERROR)) {
- if (Flags & NV_TX_UNDERFLOW)
- np->stats.tx_fifo_errors++;
- if (Flags & NV_TX_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
- } else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += skb->len;
- }
- nv_release_txskb(dev, i);
+ if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+ NV_TX_UNDERFLOW|NV_TX_ERROR)) {
+ if (Flags & NV_TX_UNDERFLOW)
+ np->stats.tx_fifo_errors++;
+ if (Flags & NV_TX_CARRIERLOST)
+ np->stats.tx_carrier_errors++;
+ np->stats.tx_errors++;
+ } else {
+ np->stats.tx_packets++;
+ np->stats.tx_bytes += np->tx_skbuff[i]->len;
}
} else {
- if (Flags & NV_TX2_LASTPACKET) {
- skb = np->tx_skbuff[i];
- if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
- NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
- if (Flags & NV_TX2_UNDERFLOW)
- np->stats.tx_fifo_errors++;
- if (Flags & NV_TX2_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
- } else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += skb->len;
- }
- nv_release_txskb(dev, i);
+ if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
+ NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
+ if (Flags & NV_TX2_UNDERFLOW)
+ np->stats.tx_fifo_errors++;
+ if (Flags & NV_TX2_CARRIERLOST)
+ np->stats.tx_carrier_errors++;
+ np->stats.tx_errors++;
+ } else {
+ np->stats.tx_packets++;
+ np->stats.tx_bytes += np->tx_skbuff[i]->len;
}
}
+ pci_unmap_single(np->pci_dev, np->tx_dma[i],
+ np->tx_skbuff[i]->len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(np->tx_skbuff[i]);
+ np->tx_skbuff[i] = NULL;
np->nic_tx++;
}
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
@@ -1146,7 +1067,7 @@ static void nv_tx_done(struct net_device *dev)
*/
static void nv_tx_timeout(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
@@ -1279,7 +1200,7 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
static void nv_rx_process(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u32 Flags;
for (;;) {
@@ -1434,7 +1355,7 @@ static void set_bufsize(struct net_device *dev)
*/
static int nv_change_mtu(struct net_device *dev, int new_mtu)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
int old_mtu;
if (new_mtu < 64 || new_mtu > np->pkt_limit)
@@ -1487,7 +1408,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
base + NvRegRingSizes);
pci_push(base);
- writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
pci_push(base);
/* restart rx engine */
@@ -1519,7 +1440,7 @@ static void nv_copy_mac_to_hw(struct net_device *dev)
*/
static int nv_set_mac_address(struct net_device *dev, void *addr)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
struct sockaddr *macaddr = (struct sockaddr*)addr;
if(!is_valid_ether_addr(macaddr->sa_data))
@@ -1554,7 +1475,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
*/
static void nv_set_multicast(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 addr[2];
u32 mask[2];
@@ -1614,7 +1535,7 @@ static void nv_set_multicast(struct net_device *dev)
static int nv_update_linkspeed(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
int adv, lpa;
int newls = np->linkspeed;
@@ -1784,7 +1705,7 @@ static void nv_link_irq(struct net_device *dev)
static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 events;
int i;
@@ -1856,7 +1777,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
static void nv_do_nic_poll(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
disable_irq(dev->irq);
@@ -1880,7 +1801,7 @@ static void nv_poll_controller(struct net_device *dev)
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
strcpy(info->driver, "forcedeth");
strcpy(info->version, FORCEDETH_VERSION);
strcpy(info->bus_info, pci_name(np->pci_dev));
@@ -1888,7 +1809,7 @@ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
wolinfo->supported = WAKE_MAGIC;
spin_lock_irq(&np->lock);
@@ -1899,7 +1820,7 @@ static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
spin_lock_irq(&np->lock);
@@ -2100,7 +2021,7 @@ static int nv_get_regs_len(struct net_device *dev)
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 *rbuf = buf;
int i;
@@ -2114,7 +2035,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void
static int nv_nway_reset(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
int ret;
spin_lock_irq(&np->lock);
@@ -2144,12 +2065,11 @@ static struct ethtool_ops ops = {
.get_regs_len = nv_get_regs_len,
.get_regs = nv_get_regs,
.nway_reset = nv_nway_reset,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int nv_open(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
int ret, oom, i;
@@ -2194,9 +2114,9 @@ static int nv_open(struct net_device *dev)
/* 5) continue setup */
writel(np->linkspeed, base + NvRegLinkSpeed);
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
- writel(np->txrxctl_bits, base + NvRegTxRxControl);
+ writel(np->desc_ver, base + NvRegTxRxControl);
pci_push(base);
- writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
@@ -2285,7 +2205,7 @@ static int nv_open(struct net_device *dev)
static int nv_close(struct net_device *dev)
{
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base;
spin_lock_irq(&np->lock);
@@ -2341,7 +2261,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (!dev)
goto out;
- np = netdev_priv(dev);
+ np = get_nvpriv(dev);
np->pci_dev = pci_dev;
spin_lock_init(&np->lock);
SET_MODULE_OWNER(dev);
@@ -2393,32 +2313,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
pci_name(pci_dev));
- } else {
- dev->features |= NETIF_F_HIGHDMA;
}
- np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
/* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
- np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
} else {
/* original packet format */
np->desc_ver = DESC_VER_1;
- np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
}
np->pkt_limit = NV_PKTLIMIT_1;
if (id->driver_data & DEV_HAS_LARGEDESC)
np->pkt_limit = NV_PKTLIMIT_2;
- if (id->driver_data & DEV_HAS_CHECKSUM) {
- np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
- dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
-#ifdef NETIF_F_TSO
- dev->features |= NETIF_F_TSO;
-#endif
- }
-
err = -ENOMEM;
np->base = ioremap(addr, NV_PCI_REGSZ);
if (!np->base)
@@ -2470,9 +2377,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->perm_addr)) {
+ if (!is_valid_ether_addr(dev->dev_addr)) {
/*
* Bad mac address. At least one bios sets the mac address
* to 01:23:45:67:89:ab
@@ -2497,9 +2403,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->wolenabled = 0;
if (np->desc_ver == DESC_VER_1) {
- np->tx_flags = NV_TX_VALID;
+ np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
} else {
- np->tx_flags = NV_TX2_VALID;
+ np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
}
np->irqmask = NVREG_IRQMASK_WANTED;
if (id->driver_data & DEV_NEED_TIMERIRQ)
@@ -2588,7 +2494,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
static void __devexit nv_remove(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
- struct fe_priv *np = netdev_priv(dev);
+ struct fe_priv *np = get_nvpriv(dev);
unregister_netdev(dev);
@@ -2619,35 +2525,35 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* CK804 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* CK804 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP51 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
@@ -2659,11 +2565,11 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{0,},
};
diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c
index ae5a2ed3b264..6518334b9280 100644
--- a/trunk/drivers/net/gianfar.c
+++ b/trunk/drivers/net/gianfar.c
@@ -29,7 +29,12 @@
* define the configuration needed by the board are defined in a
* board structure in arch/ppc/platforms (though I do not
* discount the possibility that other architectures could one
- * day be supported.
+ * day be supported. One assumption the driver currently makes
+ * is that the PHY is configured in such a way to advertise all
+ * capabilities. This is a sensible default, and on certain
+ * PHYs, changing this default encounters substantial errata
+ * issues. Future versions may remove this requirement, but for
+ * now, it is best for the firmware to ensure this is the case.
*
* The Gianfar Ethernet Controller uses a ring of buffer
* descriptors. The beginning is indicated by a register
@@ -42,7 +47,7 @@
* corresponding bit in the IMASK register is also set (if
* interrupt coalescing is active, then the interrupt may not
* happen immediately, but will wait until either a set number
- * of frames or amount of time have passed). In NAPI, the
+ * of frames or amount of time have passed.). In NAPI, the
* interrupt handler will signal there is work to be done, and
* exit. Without NAPI, the packet(s) will be handled
* immediately. Both methods will start at the last known empty
@@ -70,7 +75,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -93,11 +97,9 @@
#include
#include
#include
-#include
-#include
#include "gianfar.h"
-#include "gianfar_mii.h"
+#include "gianfar_phy.h"
#define TX_TIMEOUT (1*HZ)
#define SKB_ALLOC_TIMEOUT 1000000
@@ -111,8 +113,9 @@
#endif
const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.2";
+const char gfar_driver_version[] = "1.1";
+int startup_gfar(struct net_device *dev);
static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void gfar_timeout(struct net_device *dev);
@@ -123,13 +126,17 @@ static int gfar_set_mac_address(struct net_device *dev);
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void gfar_phy_change(void *data);
+static void gfar_phy_timer(unsigned long data);
static void adjust_link(struct net_device *dev);
static void init_registers(struct net_device *dev);
static int init_phy(struct net_device *dev);
static int gfar_probe(struct device *device);
static int gfar_remove(struct device *device);
-static void free_skb_resources(struct gfar_private *priv);
+void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI
@@ -137,6 +144,7 @@ static int gfar_poll(struct net_device *dev, int *budget);
#endif
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
+static void gfar_phy_startup_timer(unsigned long data);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
@@ -154,9 +162,6 @@ int gfar_uses_fcb(struct gfar_private *priv)
else
return 0;
}
-
-/* Set up the ethernet device structure, private data,
- * and anything else we need before we start */
static int gfar_probe(struct device *device)
{
u32 tempval;
@@ -170,7 +175,7 @@ static int gfar_probe(struct device *device)
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
- if (NULL == einfo) {
+ if (einfo == NULL) {
printk(KERN_ERR "gfar %d: Missing additional data!\n",
pdev->id);
@@ -180,7 +185,7 @@ static int gfar_probe(struct device *device)
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof (*priv));
- if (NULL == dev)
+ if (dev == NULL)
return -ENOMEM;
priv = netdev_priv(dev);
@@ -202,11 +207,20 @@ static int gfar_probe(struct device *device)
priv->regs = (struct gfar *)
ioremap(r->start, sizeof (struct gfar));
- if (NULL == priv->regs) {
+ if (priv->regs == NULL) {
err = -ENOMEM;
goto regs_fail;
}
+ /* Set the PHY base address */
+ priv->phyregs = (struct gfar *)
+ ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
+
+ if (priv->phyregs == NULL) {
+ err = -ENOMEM;
+ goto phy_regs_fail;
+ }
+
spin_lock_init(&priv->lock);
dev_set_drvdata(device, dev);
@@ -372,10 +386,12 @@ static int gfar_probe(struct device *device)
return 0;
register_fail:
+ iounmap((void *) priv->phyregs);
+phy_regs_fail:
iounmap((void *) priv->regs);
regs_fail:
free_netdev(dev);
- return err;
+ return -ENOMEM;
}
static int gfar_remove(struct device *device)
@@ -386,41 +402,108 @@ static int gfar_remove(struct device *device)
dev_set_drvdata(device, NULL);
iounmap((void *) priv->regs);
+ iounmap((void *) priv->phyregs);
free_netdev(dev);
return 0;
}
-/* Initializes driver's PHY state, and attaches to the PHY.
- * Returns 0 on success.
+/* Configure the PHY for dev.
+ * returns 0 if success. -1 if failure
*/
static int init_phy(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- uint gigabit_support =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- SUPPORTED_1000baseT_Full : 0;
- struct phy_device *phydev;
+ struct phy_info *curphy;
+ unsigned int timeout = PHY_INIT_TIMEOUT;
+ struct gfar *phyregs = priv->phyregs;
+ struct gfar_mii_info *mii_info;
+ int err;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
+ mii_info = kmalloc(sizeof(struct gfar_mii_info),
+ GFP_KERNEL);
+
+ if(NULL == mii_info) {
+ if (netif_msg_ifup(priv))
+ printk(KERN_ERR "%s: Could not allocate mii_info\n",
+ dev->name);
+ return -ENOMEM;
+ }
+
+ mii_info->speed = SPEED_1000;
+ mii_info->duplex = DUPLEX_FULL;
+ mii_info->pause = 0;
+ mii_info->link = 1;
+
+ mii_info->advertising = (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Full);
+ mii_info->autoneg = 1;
- if (IS_ERR(phydev)) {
- printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
- return PTR_ERR(phydev);
+ spin_lock_init(&mii_info->mdio_lock);
+
+ mii_info->mii_id = priv->einfo->phyid;
+
+ mii_info->dev = dev;
+
+ mii_info->mdio_read = &read_phy_reg;
+ mii_info->mdio_write = &write_phy_reg;
+
+ priv->mii_info = mii_info;
+
+ /* Reset the management interface */
+ gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
+
+ /* Setup the MII Mgmt clock speed */
+ gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
+
+ /* Wait until the bus is free */
+ while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
+ timeout--)
+ cpu_relax();
+
+ if(timeout <= 0) {
+ printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+ dev->name);
+ err = -1;
+ goto bus_fail;
+ }
+
+ /* get info for this PHY */
+ curphy = get_phy_info(priv->mii_info);
+
+ if (curphy == NULL) {
+ if (netif_msg_ifup(priv))
+ printk(KERN_ERR "%s: No PHY found\n", dev->name);
+ err = -1;
+ goto no_phy;
}
- /* Remove any features not supported by the controller */
- phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
- phydev->advertising = phydev->supported;
+ mii_info->phyinfo = curphy;
- priv->phydev = phydev;
+ /* Run the commands which initialize the PHY */
+ if(curphy->init) {
+ err = curphy->init(priv->mii_info);
+
+ if (err)
+ goto phy_init_fail;
+ }
return 0;
+
+phy_init_fail:
+no_phy:
+bus_fail:
+ kfree(mii_info);
+
+ return err;
}
static void init_registers(struct net_device *dev)
@@ -520,13 +603,24 @@ void stop_gfar(struct net_device *dev)
struct gfar *regs = priv->regs;
unsigned long flags;
- phy_stop(priv->phydev);
-
/* Lock it down */
spin_lock_irqsave(&priv->lock, flags);
+ /* Tell the kernel the link is down */
+ priv->mii_info->link = 0;
+ adjust_link(dev);
+
gfar_halt(dev);
+ if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
+ /* Clear any pending interrupts */
+ mii_clear_phy_interrupt(priv->mii_info);
+
+ /* Disable PHY Interrupts */
+ mii_configure_phy_interrupt(priv->mii_info,
+ MII_INTERRUPT_DISABLED);
+ }
+
spin_unlock_irqrestore(&priv->lock, flags);
/* Free the IRQs */
@@ -535,7 +629,13 @@ void stop_gfar(struct net_device *dev)
free_irq(priv->interruptTransmit, dev);
free_irq(priv->interruptReceive, dev);
} else {
- free_irq(priv->interruptTransmit, dev);
+ free_irq(priv->interruptTransmit, dev);
+ }
+
+ if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
+ free_irq(priv->einfo->interruptPHY, dev);
+ } else {
+ del_timer_sync(&priv->phy_info_timer);
}
free_skb_resources(priv);
@@ -549,7 +649,7 @@ void stop_gfar(struct net_device *dev)
/* If there are any tx skbs or rx skbs still around, free them.
* Then free tx_skbuff and rx_skbuff */
-static void free_skb_resources(struct gfar_private *priv)
+void free_skb_resources(struct gfar_private *priv)
{
struct rxbd8 *rxbdp;
struct txbd8 *txbdp;
@@ -670,7 +770,7 @@ int startup_gfar(struct net_device *dev)
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
priv->tx_ring_size, GFP_KERNEL);
- if (NULL == priv->tx_skbuff) {
+ if (priv->tx_skbuff == NULL) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
dev->name);
@@ -685,7 +785,7 @@ int startup_gfar(struct net_device *dev)
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
priv->rx_ring_size, GFP_KERNEL);
- if (NULL == priv->rx_skbuff) {
+ if (priv->rx_skbuff == NULL) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
dev->name);
@@ -779,7 +879,13 @@ int startup_gfar(struct net_device *dev)
}
}
- phy_start(priv->phydev);
+ /* Set up the PHY change work queue */
+ INIT_WORK(&priv->tq, gfar_phy_change, dev);
+
+ init_timer(&priv->phy_info_timer);
+ priv->phy_info_timer.function = &gfar_phy_startup_timer;
+ priv->phy_info_timer.data = (unsigned long) priv->mii_info;
+ mod_timer(&priv->phy_info_timer, jiffies + HZ);
/* Configure the coalescing support */
if (priv->txcoalescing)
@@ -827,6 +933,11 @@ int startup_gfar(struct net_device *dev)
priv->tx_bd_base,
gfar_read(®s->tbase0));
+ if (priv->mii_info->phyinfo->close)
+ priv->mii_info->phyinfo->close(priv->mii_info);
+
+ kfree(priv->mii_info);
+
return err;
}
@@ -924,7 +1035,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbdp->status &= TXBD_WRAP;
/* Set up checksumming */
- if ((dev->features & NETIF_F_IP_CSUM)
+ if ((dev->features & NETIF_F_IP_CSUM)
&& (CHECKSUM_HW == skb->ip_summed)) {
fcb = gfar_add_fcb(skb, txbdp);
gfar_tx_checksum(skb, fcb);
@@ -992,9 +1103,11 @@ static int gfar_close(struct net_device *dev)
struct gfar_private *priv = netdev_priv(dev);
stop_gfar(dev);
- /* Disconnect from the PHY */
- phy_disconnect(priv->phydev);
- priv->phydev = NULL;
+ /* Shutdown the PHY */
+ if (priv->mii_info->phyinfo->close)
+ priv->mii_info->phyinfo->close(priv->mii_info);
+
+ kfree(priv->mii_info);
netif_stop_queue(dev);
@@ -1230,7 +1343,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
while ((!skb) && timeout--)
skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
- if (NULL == skb)
+ if (skb == NULL)
return NULL;
/* We need the data buffer to be aligned properly. We will reserve
@@ -1377,7 +1490,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
struct gfar_private *priv = netdev_priv(dev);
struct rxfcb *fcb = NULL;
- if (NULL == skb) {
+ if (skb == NULL) {
if (netif_msg_rx_err(priv))
printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
priv->stats.rx_dropped++;
@@ -1605,9 +1718,131 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct gfar_private *priv = netdev_priv(dev);
+
+ /* Clear the interrupt */
+ mii_clear_phy_interrupt(priv->mii_info);
+
+ /* Disable PHY interrupts */
+ mii_configure_phy_interrupt(priv->mii_info,
+ MII_INTERRUPT_DISABLED);
+
+ /* Schedule the phy change */
+ schedule_work(&priv->tq);
+
+ return IRQ_HANDLED;
+}
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void gfar_phy_change(void *data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct gfar_private *priv = netdev_priv(dev);
+ int result = 0;
+
+ /* Delay to give the PHY a chance to change the
+ * register state */
+ msleep(1);
+
+ /* Update the link, speed, duplex */
+ result = priv->mii_info->phyinfo->read_status(priv->mii_info);
+
+ /* Adjust the known status as long as the link
+ * isn't still coming up */
+ if((0 == result) || (priv->mii_info->link == 0))
+ adjust_link(dev);
+
+ /* Reenable interrupts, if needed */
+ if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
+ mii_configure_phy_interrupt(priv->mii_info,
+ MII_INTERRUPT_ENABLED);
+}
+
+/* Called every so often on systems that don't interrupt
+ * the core for PHY changes */
+static void gfar_phy_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct gfar_private *priv = netdev_priv(dev);
+
+ schedule_work(&priv->tq);
+
+ mod_timer(&priv->phy_info_timer, jiffies +
+ GFAR_PHY_CHANGE_TIME * HZ);
+}
+
+/* Keep trying aneg for some time
+ * If, after GFAR_AN_TIMEOUT seconds, it has not
+ * finished, we switch to forced.
+ * Either way, once the process has completed, we either
+ * request the interrupt, or switch the timer over to
+ * using gfar_phy_timer to check status */
+static void gfar_phy_startup_timer(unsigned long data)
+{
+ int result;
+ static int secondary = GFAR_AN_TIMEOUT;
+ struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
+ struct gfar_private *priv = netdev_priv(mii_info->dev);
+
+ /* Configure the Auto-negotiation */
+ result = mii_info->phyinfo->config_aneg(mii_info);
+
+ /* If autonegotiation failed to start, and
+ * we haven't timed out, reset the timer, and return */
+ if (result && secondary--) {
+ mod_timer(&priv->phy_info_timer, jiffies + HZ);
+ return;
+ } else if (result) {
+ /* Couldn't start autonegotiation.
+ * Try switching to forced */
+ mii_info->autoneg = 0;
+ result = mii_info->phyinfo->config_aneg(mii_info);
+
+ /* Forcing failed! Give up */
+ if(result) {
+ if (netif_msg_link(priv))
+ printk(KERN_ERR "%s: Forcing failed!\n",
+ mii_info->dev->name);
+ return;
+ }
+ }
+
+ /* Kill the timer so it can be restarted */
+ del_timer_sync(&priv->phy_info_timer);
+
+ /* Grab the PHY interrupt, if necessary/possible */
+ if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
+ if (request_irq(priv->einfo->interruptPHY,
+ phy_interrupt,
+ SA_SHIRQ,
+ "phy_interrupt",
+ mii_info->dev) < 0) {
+ if (netif_msg_intr(priv))
+ printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
+ mii_info->dev->name,
+ priv->einfo->interruptPHY);
+ } else {
+ mii_configure_phy_interrupt(priv->mii_info,
+ MII_INTERRUPT_ENABLED);
+ return;
+ }
+ }
+
+ /* Start the timer again, this time in order to
+ * handle a change in status */
+ init_timer(&priv->phy_info_timer);
+ priv->phy_info_timer.function = &gfar_phy_timer;
+ priv->phy_info_timer.data = (unsigned long) mii_info->dev;
+ mod_timer(&priv->phy_info_timer, jiffies +
+ GFAR_PHY_CHANGE_TIME * HZ);
+}
+
/* Called every time the controller might need to be made
* aware of new link state. The PHY code conveys this
- * information through variables in the phydev structure, and this
+ * information through variables in the priv structure, and this
* function converts those variables into the appropriate
* register values, and can bring down the device if needed.
*/
@@ -1615,69 +1850,85 @@ static void adjust_link(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
- unsigned long flags;
- struct phy_device *phydev = priv->phydev;
- int new_state = 0;
-
- spin_lock_irqsave(&priv->lock, flags);
- if (phydev->link) {
- u32 tempval = gfar_read(®s->maccfg2);
+ u32 tempval;
+ struct gfar_mii_info *mii_info = priv->mii_info;
+ if (mii_info->link) {
/* Now we make sure that we can be in full duplex mode.
* If not, we operate in half-duplex mode. */
- if (phydev->duplex != priv->oldduplex) {
- new_state = 1;
- if (!(phydev->duplex))
+ if (mii_info->duplex != priv->oldduplex) {
+ if (!(mii_info->duplex)) {
+ tempval = gfar_read(®s->maccfg2);
tempval &= ~(MACCFG2_FULL_DUPLEX);
- else
+ gfar_write(®s->maccfg2, tempval);
+
+ if (netif_msg_link(priv))
+ printk(KERN_INFO "%s: Half Duplex\n",
+ dev->name);
+ } else {
+ tempval = gfar_read(®s->maccfg2);
tempval |= MACCFG2_FULL_DUPLEX;
+ gfar_write(®s->maccfg2, tempval);
- priv->oldduplex = phydev->duplex;
+ if (netif_msg_link(priv))
+ printk(KERN_INFO "%s: Full Duplex\n",
+ dev->name);
+ }
+
+ priv->oldduplex = mii_info->duplex;
}
- if (phydev->speed != priv->oldspeed) {
- new_state = 1;
- switch (phydev->speed) {
+ if (mii_info->speed != priv->oldspeed) {
+ switch (mii_info->speed) {
case 1000:
+ tempval = gfar_read(®s->maccfg2);
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
+ gfar_write(®s->maccfg2, tempval);
break;
case 100:
case 10:
+ tempval = gfar_read(®s->maccfg2);
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+ gfar_write(®s->maccfg2, tempval);
break;
default:
if (netif_msg_link(priv))
printk(KERN_WARNING
- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, phydev->speed);
+ "%s: Ack! Speed (%d) is not 10/100/1000!\n",
+ dev->name, mii_info->speed);
break;
}
- priv->oldspeed = phydev->speed;
- }
+ if (netif_msg_link(priv))
+ printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
+ mii_info->speed);
- gfar_write(®s->maccfg2, tempval);
+ priv->oldspeed = mii_info->speed;
+ }
if (!priv->oldlink) {
- new_state = 1;
+ if (netif_msg_link(priv))
+ printk(KERN_INFO "%s: Link is up\n", dev->name);
priv->oldlink = 1;
+ netif_carrier_on(dev);
netif_schedule(dev);
}
- } else if (priv->oldlink) {
- new_state = 1;
- priv->oldlink = 0;
- priv->oldspeed = 0;
- priv->oldduplex = -1;
+ } else {
+ if (priv->oldlink) {
+ if (netif_msg_link(priv))
+ printk(KERN_INFO "%s: Link is down\n",
+ dev->name);
+ priv->oldlink = 0;
+ priv->oldspeed = 0;
+ priv->oldduplex = -1;
+ netif_carrier_off(dev);
+ }
}
-
- if (new_state && netif_msg_link(priv))
- phy_print_status(phydev);
-
- spin_unlock_irqrestore(&priv->lock, flags);
}
+
/* Update the hash table based on the current list of multicast
* addresses we subscribe to. Also, change the promiscuity of
* the device based on the flags (this function is called
@@ -1871,23 +2122,12 @@ static struct device_driver gfar_driver = {
static int __init gfar_init(void)
{
- int err = gfar_mdio_init();
-
- if (err)
- return err;
-
- err = driver_register(&gfar_driver);
-
- if (err)
- gfar_mdio_exit();
-
- return err;
+ return driver_register(&gfar_driver);
}
static void __exit gfar_exit(void)
{
driver_unregister(&gfar_driver);
- gfar_mdio_exit();
}
module_init(gfar_init);
diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h
index c77ca6c0d04a..28af087d9fbb 100644
--- a/trunk/drivers/net/gianfar.h
+++ b/trunk/drivers/net/gianfar.h
@@ -17,6 +17,7 @@
*
* Still left to do:
* -Add support for module parameters
+ * -Add support for ethtool -s
* -Add patch for ethtool phys id
*/
#ifndef __GIANFAR_H
@@ -36,8 +37,7 @@
#include
#include
#include
-#include
-#include
+#include
#include
#include
@@ -48,8 +48,7 @@
#include
#include
#include
-#include
-#include "gianfar_mii.h"
+#include "gianfar_phy.h"
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
@@ -74,7 +73,7 @@
#define PHY_INIT_TIMEOUT 100000
#define GFAR_PHY_CHANGE_TIME 2
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
#define DRV_NAME "gfar-enet"
extern const char gfar_driver_name[];
extern const char gfar_driver_version[];
@@ -579,7 +578,12 @@ struct gfar {
u32 hafdup; /* 0x.50c - Half Duplex Register */
u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
u8 res18[12];
- u8 gfar_mii_regs[24]; /* See gianfar_phy.h */
+ u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
+ u32 miimcom; /* 0x.524 - MII Management Command Register */
+ u32 miimadd; /* 0x.528 - MII Management Address Register */
+ u32 miimcon; /* 0x.52c - MII Management Control Register */
+ u32 miimstat; /* 0x.530 - MII Management Status Register */
+ u32 miimind; /* 0x.534 - MII Management Indicator Register */
u8 res19[4];
u32 ifstat; /* 0x.53c - Interface Status Register */
u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
@@ -684,6 +688,9 @@ struct gfar_private {
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
u32 *hash_regs[16];
int hash_width;
+ struct gfar *phyregs;
+ struct work_struct tq;
+ struct timer_list phy_info_timer;
struct net_device_stats stats; /* linux network statistics */
struct gfar_extra_stats extra_stats;
spinlock_t lock;
@@ -703,8 +710,7 @@ struct gfar_private {
unsigned int interruptError;
struct gianfar_platform_data *einfo;
- struct phy_device *phydev;
- struct mii_bus *mii_bus;
+ struct gfar_mii_info *mii_info;
int oldspeed;
int oldduplex;
int oldlink;
@@ -726,12 +732,4 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val)
extern struct ethtool_ops *gfar_op_array[];
-extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
-extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
- int enable, u32 regnum, u32 read);
-void gfar_setup_stashing(struct net_device *dev);
-
#endif /* __GIANFAR_H */
diff --git a/trunk/drivers/net/gianfar_ethtool.c b/trunk/drivers/net/gianfar_ethtool.c
index 68e3578e7613..a451de629197 100644
--- a/trunk/drivers/net/gianfar_ethtool.c
+++ b/trunk/drivers/net/gianfar_ethtool.c
@@ -39,18 +39,17 @@
#include
#include
#include
-#include
-#include
#include "gianfar.h"
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_halt(struct net_device *dev);
extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
-#define GFAR_MAX_COAL_USECS 0xffff
-#define GFAR_MAX_COAL_FRAMES 0xff
static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 * buf);
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
@@ -183,32 +182,38 @@ static void gfar_gdrvinfo(struct net_device *dev, struct
drvinfo->eedump_len = 0;
}
-
-static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct phy_device *phydev = priv->phydev;
-
- if (NULL == phydev)
- return -ENODEV;
-
- return phy_ethtool_sset(phydev, cmd);
-}
-
-
/* Return the current settings in the ethtool_cmd structure */
static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
- struct phy_device *phydev = priv->phydev;
-
- if (NULL == phydev)
- return -ENODEV;
-
+ uint gigabit_support =
+ priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+ SUPPORTED_1000baseT_Full : 0;
+ uint gigabit_advert =
+ priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+ ADVERTISED_1000baseT_Full: 0;
+
+ cmd->supported = (SUPPORTED_10baseT_Half
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | gigabit_support | SUPPORTED_Autoneg);
+
+ /* For now, we always advertise everything */
+ cmd->advertising = (ADVERTISED_10baseT_Half
+ | ADVERTISED_100baseT_Half
+ | ADVERTISED_100baseT_Full
+ | gigabit_advert | ADVERTISED_Autoneg);
+
+ cmd->speed = priv->mii_info->speed;
+ cmd->duplex = priv->mii_info->duplex;
+ cmd->port = PORT_MII;
+ cmd->phy_address = priv->mii_info->mii_id;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->autoneg = AUTONEG_ENABLE;
cmd->maxtxpkt = priv->txcount;
cmd->maxrxpkt = priv->rxcount;
- return phy_ethtool_gset(phydev, cmd);
+ return 0;
}
/* Return the length of the register structure */
@@ -236,14 +241,14 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->phydev->speed) {
- case SPEED_1000:
+ switch (priv->mii_info->speed) {
+ case 1000:
count = GFAR_GBIT_TIME;
break;
- case SPEED_100:
+ case 100:
count = GFAR_100_TIME;
break;
- case SPEED_10:
+ case 10:
default:
count = GFAR_10_TIME;
break;
@@ -260,14 +265,14 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->phydev->speed) {
- case SPEED_1000:
+ switch (priv->mii_info->speed) {
+ case 1000:
count = GFAR_GBIT_TIME;
break;
- case SPEED_100:
+ case 100:
count = GFAR_100_TIME;
break;
- case SPEED_10:
+ case 10:
default:
count = GFAR_10_TIME;
break;
@@ -287,9 +292,6 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
- if (NULL == priv->phydev)
- return -ENODEV;
-
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
cvals->rx_max_coalesced_frames = priv->rxcount;
@@ -346,22 +348,6 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
else
priv->rxcoalescing = 1;
- if (NULL == priv->phydev)
- return -ENODEV;
-
- /* Check the bounds of the values */
- if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
- pr_info("Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
- return -EINVAL;
- }
-
- if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
- pr_info("Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
- return -EINVAL;
- }
-
priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
priv->rxcount = cvals->rx_max_coalesced_frames;
@@ -372,19 +358,6 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
else
priv->txcoalescing = 1;
- /* Check the bounds of the values */
- if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
- pr_info("Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
- return -EINVAL;
- }
-
- if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
- pr_info("Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
- return -EINVAL;
- }
-
priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
priv->txcount = cvals->tx_max_coalesced_frames;
@@ -563,7 +536,6 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
- .set_settings = gfar_ssettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
.get_regs = gfar_get_regs,
diff --git a/trunk/drivers/net/gianfar_mii.c b/trunk/drivers/net/gianfar_mii.c
deleted file mode 100644
index 1eca1dbca7f1..000000000000
--- a/trunk/drivers/net/gianfar_mii.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * drivers/net/gianfar_mii.c
- *
- * Gianfar Ethernet Driver -- MIIM bus implementation
- * Provides Bus interface for MIIM regs
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, 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.
- *
- */
-
-#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 "gianfar.h"
-#include "gianfar_mii.h"
-
-/* Write value to the PHY at mii_id at register regnum,
- * on the bus, waiting until the write is done before returning.
- * All PHY configuration is done through the TSEC1 MIIM regs */
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
-{
- struct gfar_mii *regs = bus->priv;
-
- /* Set the PHY address and the register address we want to write */
- gfar_write(®s->miimadd, (mii_id << 8) | regnum);
-
- /* Write out the value we want */
- gfar_write(®s->miimcon, value);
-
- /* Wait for the transaction to finish */
- while (gfar_read(®s->miimind) & MIIMIND_BUSY)
- cpu_relax();
-
- return 0;
-}
-
-/* Read the bus for PHY at addr mii_id, register regnum, and
- * return the value. Clears miimcom first. All PHY
- * configuration has to be done through the TSEC1 MIIM regs */
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-{
- struct gfar_mii *regs = bus->priv;
- u16 value;
-
- /* Set the PHY address and the register address we want to read */
- gfar_write(®s->miimadd, (mii_id << 8) | regnum);
-
- /* Clear miimcom, and then initiate a read */
- gfar_write(®s->miimcom, 0);
- gfar_write(®s->miimcom, MII_READ_COMMAND);
-
- /* Wait for the transaction to finish */
- while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
- cpu_relax();
-
- /* Grab the value of the register from miimstat */
- value = gfar_read(®s->miimstat);
-
- return value;
-}
-
-
-/* Reset the MIIM registers, and wait for the bus to free */
-int gfar_mdio_reset(struct mii_bus *bus)
-{
- struct gfar_mii *regs = bus->priv;
- unsigned int timeout = PHY_INIT_TIMEOUT;
-
- spin_lock_bh(&bus->mdio_lock);
-
- /* Reset the management interface */
- gfar_write(®s->miimcfg, MIIMCFG_RESET);
-
- /* Setup the MII Mgmt clock speed */
- gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE);
-
- /* Wait until the bus is free */
- while ((gfar_read(®s->miimind) & MIIMIND_BUSY) &&
- timeout--)
- cpu_relax();
-
- spin_unlock_bh(&bus->mdio_lock);
-
- if(timeout <= 0) {
- printk(KERN_ERR "%s: The MII Bus is stuck!\n",
- bus->name);
- return -EBUSY;
- }
-
- return 0;
-}
-
-
-int gfar_mdio_probe(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct gianfar_mdio_data *pdata;
- struct gfar_mii *regs;
- struct mii_bus *new_bus;
- int err = 0;
-
- if (NULL == dev)
- return -EINVAL;
-
- new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
-
- if (NULL == new_bus)
- return -ENOMEM;
-
- new_bus->name = "Gianfar MII Bus",
- new_bus->read = &gfar_mdio_read,
- new_bus->write = &gfar_mdio_write,
- new_bus->reset = &gfar_mdio_reset,
- new_bus->id = pdev->id;
-
- pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
-
- if (NULL == pdata) {
- printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
- return -ENODEV;
- }
-
- /* Set the PHY base address */
- regs = (struct gfar_mii *) ioremap(pdata->paddr,
- sizeof (struct gfar_mii));
-
- if (NULL == regs) {
- err = -ENOMEM;
- goto reg_map_fail;
- }
-
- new_bus->priv = regs;
-
- new_bus->irq = pdata->irq;
-
- new_bus->dev = dev;
- dev_set_drvdata(dev, new_bus);
-
- err = mdiobus_register(new_bus);
-
- if (0 != err) {
- printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
- new_bus->name);
- goto bus_register_fail;
- }
-
- return 0;
-
-bus_register_fail:
- iounmap((void *) regs);
-reg_map_fail:
- kfree(new_bus);
-
- return err;
-}
-
-
-int gfar_mdio_remove(struct device *dev)
-{
- struct mii_bus *bus = dev_get_drvdata(dev);
-
- mdiobus_unregister(bus);
-
- dev_set_drvdata(dev, NULL);
-
- iounmap((void *) (&bus->priv));
- bus->priv = NULL;
- kfree(bus);
-
- return 0;
-}
-
-static struct device_driver gianfar_mdio_driver = {
- .name = "fsl-gianfar_mdio",
- .bus = &platform_bus_type,
- .probe = gfar_mdio_probe,
- .remove = gfar_mdio_remove,
-};
-
-int __init gfar_mdio_init(void)
-{
- return driver_register(&gianfar_mdio_driver);
-}
-
-void __exit gfar_mdio_exit(void)
-{
- driver_unregister(&gianfar_mdio_driver);
-}
diff --git a/trunk/drivers/net/gianfar_mii.h b/trunk/drivers/net/gianfar_mii.h
deleted file mode 100644
index 56e5665d5c9b..000000000000
--- a/trunk/drivers/net/gianfar_mii.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * drivers/net/gianfar_mii.h
- *
- * Gianfar Ethernet Driver -- MII Management Bus Implementation
- * Driver for the MDIO bus controller in the Gianfar register space
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, 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.
- *
- */
-#ifndef __GIANFAR_MII_H
-#define __GIANFAR_MII_H
-
-#define MIIMIND_BUSY 0x00000001
-#define MIIMIND_NOTVALID 0x00000004
-
-#define MII_READ_COMMAND 0x00000001
-
-#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
- | SUPPORTED_100baseT_Half \
- | SUPPORTED_100baseT_Full \
- | SUPPORTED_Autoneg \
- | SUPPORTED_MII)
-
-struct gfar_mii {
- u32 miimcfg; /* 0x.520 - MII Management Config Register */
- u32 miimcom; /* 0x.524 - MII Management Command Register */
- u32 miimadd; /* 0x.528 - MII Management Address Register */
- u32 miimcon; /* 0x.52c - MII Management Control Register */
- u32 miimstat; /* 0x.530 - MII Management Status Register */
- u32 miimind; /* 0x.534 - MII Management Indicator Register */
-};
-
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
-int __init gfar_mdio_init(void);
-void __exit gfar_mdio_exit(void);
-#endif /* GIANFAR_PHY_H */
diff --git a/trunk/drivers/net/gianfar_phy.c b/trunk/drivers/net/gianfar_phy.c
new file mode 100644
index 000000000000..7c965f268a82
--- /dev/null
+++ b/trunk/drivers/net/gianfar_phy.c
@@ -0,0 +1,661 @@
+/*
+ * drivers/net/gianfar_phy.c
+ *
+ * Gianfar Ethernet Driver -- PHY handling
+ * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, 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.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "gianfar.h"
+#include "gianfar_phy.h"
+
+static void config_genmii_advert(struct gfar_mii_info *mii_info);
+static void genmii_setup_forced(struct gfar_mii_info *mii_info);
+static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
+static int gbit_config_aneg(struct gfar_mii_info *mii_info);
+static int genmii_config_aneg(struct gfar_mii_info *mii_info);
+static int genmii_update_link(struct gfar_mii_info *mii_info);
+static int genmii_read_status(struct gfar_mii_info *mii_info);
+u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
+void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
+
+/* Write value to the PHY for this device to the register at regnum, */
+/* waiting until the write is done before it returns. All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar *regbase = priv->phyregs;
+
+ /* Set the PHY address and the register address we want to write */
+ gfar_write(®base->miimadd, (mii_id << 8) | regnum);
+
+ /* Write out the value we want */
+ gfar_write(®base->miimcon, value);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(®base->miimind) & MIIMIND_BUSY)
+ cpu_relax();
+}
+
+/* Reads from register regnum in the PHY for device dev, */
+/* returning the value. Clears miimcom first. All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar *regbase = priv->phyregs;
+ u16 value;
+
+ /* Set the PHY address and the register address we want to read */
+ gfar_write(®base->miimadd, (mii_id << 8) | regnum);
+
+ /* Clear miimcom, and then initiate a read */
+ gfar_write(®base->miimcom, 0);
+ gfar_write(®base->miimcom, MII_READ_COMMAND);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+ cpu_relax();
+
+ /* Grab the value of the register from miimstat */
+ value = gfar_read(®base->miimstat);
+
+ return value;
+}
+
+void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
+{
+ if(mii_info->phyinfo->ack_interrupt)
+ mii_info->phyinfo->ack_interrupt(mii_info);
+}
+
+
+void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
+{
+ mii_info->interrupts = interrupts;
+ if(mii_info->phyinfo->config_intr)
+ mii_info->phyinfo->config_intr(mii_info);
+}
+
+
+/* Writes MII_ADVERTISE with the appropriate values, after
+ * sanitizing advertise to make sure only supported features
+ * are advertised
+ */
+static void config_genmii_advert(struct gfar_mii_info *mii_info)
+{
+ u32 advertise;
+ u16 adv;
+
+ /* Only allow advertising what this PHY supports */
+ mii_info->advertising &= mii_info->phyinfo->features;
+ advertise = mii_info->advertising;
+
+ /* Setup standard advertisement */
+ adv = phy_read(mii_info, MII_ADVERTISE);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ phy_write(mii_info, MII_ADVERTISE, adv);
+}
+
+static void genmii_setup_forced(struct gfar_mii_info *mii_info)
+{
+ u16 ctrl;
+ u32 features = mii_info->phyinfo->features;
+
+ ctrl = phy_read(mii_info, MII_BMCR);
+
+ ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
+ ctrl |= BMCR_RESET;
+
+ switch(mii_info->speed) {
+ case SPEED_1000:
+ if(features & (SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full)) {
+ ctrl |= BMCR_SPEED1000;
+ break;
+ }
+ mii_info->speed = SPEED_100;
+ case SPEED_100:
+ if (features & (SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full)) {
+ ctrl |= BMCR_SPEED100;
+ break;
+ }
+ mii_info->speed = SPEED_10;
+ case SPEED_10:
+ if (features & (SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full))
+ break;
+ default: /* Unsupported speed! */
+ printk(KERN_ERR "%s: Bad speed!\n",
+ mii_info->dev->name);
+ break;
+ }
+
+ phy_write(mii_info, MII_BMCR, ctrl);
+}
+
+
+/* Enable and Restart Autonegotiation */
+static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
+{
+ u16 ctl;
+
+ ctl = phy_read(mii_info, MII_BMCR);
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ phy_write(mii_info, MII_BMCR, ctl);
+}
+
+
+static int gbit_config_aneg(struct gfar_mii_info *mii_info)
+{
+ u16 adv;
+ u32 advertise;
+
+ if(mii_info->autoneg) {
+ /* Configure the ADVERTISE register */
+ config_genmii_advert(mii_info);
+ advertise = mii_info->advertising;
+
+ adv = phy_read(mii_info, MII_1000BASETCONTROL);
+ adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+ MII_1000BASETCONTROL_HALFDUPLEXCAP);
+ if (advertise & SUPPORTED_1000baseT_Half)
+ adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+ if (advertise & SUPPORTED_1000baseT_Full)
+ adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+ phy_write(mii_info, MII_1000BASETCONTROL, adv);
+
+ /* Start/Restart aneg */
+ genmii_restart_aneg(mii_info);
+ } else
+ genmii_setup_forced(mii_info);
+
+ return 0;
+}
+
+static int marvell_config_aneg(struct gfar_mii_info *mii_info)
+{
+ /* The Marvell PHY has an errata which requires
+ * that certain registers get written in order
+ * to restart autonegotiation */
+ phy_write(mii_info, MII_BMCR, BMCR_RESET);
+
+ phy_write(mii_info, 0x1d, 0x1f);
+ phy_write(mii_info, 0x1e, 0x200c);
+ phy_write(mii_info, 0x1d, 0x5);
+ phy_write(mii_info, 0x1e, 0);
+ phy_write(mii_info, 0x1e, 0x100);
+
+ gbit_config_aneg(mii_info);
+
+ return 0;
+}
+static int genmii_config_aneg(struct gfar_mii_info *mii_info)
+{
+ if (mii_info->autoneg) {
+ config_genmii_advert(mii_info);
+ genmii_restart_aneg(mii_info);
+ } else
+ genmii_setup_forced(mii_info);
+
+ return 0;
+}
+
+
+static int genmii_update_link(struct gfar_mii_info *mii_info)
+{
+ u16 status;
+
+ /* Do a fake read */
+ phy_read(mii_info, MII_BMSR);
+
+ /* Read link and autonegotiation status */
+ status = phy_read(mii_info, MII_BMSR);
+ if ((status & BMSR_LSTATUS) == 0)
+ mii_info->link = 0;
+ else
+ mii_info->link = 1;
+
+ /* If we are autonegotiating, and not done,
+ * return an error */
+ if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
+ return -EAGAIN;
+
+ return 0;
+}
+
+static int genmii_read_status(struct gfar_mii_info *mii_info)
+{
+ u16 status;
+ int err;
+
+ /* Update the link, but return if there
+ * was an error */
+ err = genmii_update_link(mii_info);
+ if (err)
+ return err;
+
+ if (mii_info->autoneg) {
+ status = phy_read(mii_info, MII_LPA);
+
+ if (status & (LPA_10FULL | LPA_100FULL))
+ mii_info->duplex = DUPLEX_FULL;
+ else
+ mii_info->duplex = DUPLEX_HALF;
+ if (status & (LPA_100FULL | LPA_100HALF))
+ mii_info->speed = SPEED_100;
+ else
+ mii_info->speed = SPEED_10;
+ mii_info->pause = 0;
+ }
+ /* On non-aneg, we assume what we put in BMCR is the speed,
+ * though magic-aneg shouldn't prevent this case from occurring
+ */
+
+ return 0;
+}
+static int marvell_read_status(struct gfar_mii_info *mii_info)
+{
+ u16 status;
+ int err;
+
+ /* Update the link, but return if there
+ * was an error */
+ err = genmii_update_link(mii_info);
+ if (err)
+ return err;
+
+ /* If the link is up, read the speed and duplex */
+ /* If we aren't autonegotiating, assume speeds
+ * are as set */
+ if (mii_info->autoneg && mii_info->link) {
+ int speed;
+ status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+
+#if 0
+ /* If speed and duplex aren't resolved,
+ * return an error. Isn't this handled
+ * by checking aneg?
+ */
+ if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
+ return -EAGAIN;
+#endif
+
+ /* Get the duplexity */
+ if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+ mii_info->duplex = DUPLEX_FULL;
+ else
+ mii_info->duplex = DUPLEX_HALF;
+
+ /* Get the speed */
+ speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
+ switch(speed) {
+ case MII_M1011_PHY_SPEC_STATUS_1000:
+ mii_info->speed = SPEED_1000;
+ break;
+ case MII_M1011_PHY_SPEC_STATUS_100:
+ mii_info->speed = SPEED_100;
+ break;
+ default:
+ mii_info->speed = SPEED_10;
+ break;
+ }
+ mii_info->pause = 0;
+ }
+
+ return 0;
+}
+
+
+static int cis820x_read_status(struct gfar_mii_info *mii_info)
+{
+ u16 status;
+ int err;
+
+ /* Update the link, but return if there
+ * was an error */
+ err = genmii_update_link(mii_info);
+ if (err)
+ return err;
+
+ /* If the link is up, read the speed and duplex */
+ /* If we aren't autonegotiating, assume speeds
+ * are as set */
+ if (mii_info->autoneg && mii_info->link) {
+ int speed;
+
+ status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+ if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
+ mii_info->duplex = DUPLEX_FULL;
+ else
+ mii_info->duplex = DUPLEX_HALF;
+
+ speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
+
+ switch (speed) {
+ case MII_CIS8201_AUXCONSTAT_GBIT:
+ mii_info->speed = SPEED_1000;
+ break;
+ case MII_CIS8201_AUXCONSTAT_100:
+ mii_info->speed = SPEED_100;
+ break;
+ default:
+ mii_info->speed = SPEED_10;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+ /* Clear the interrupts by reading the reg */
+ phy_read(mii_info, MII_M1011_IEVENT);
+
+ return 0;
+}
+
+static int marvell_config_intr(struct gfar_mii_info *mii_info)
+{
+ if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
+ phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+ else
+ phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+ return 0;
+}
+
+static int cis820x_init(struct gfar_mii_info *mii_info)
+{
+ phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
+ MII_CIS8201_AUXCONSTAT_INIT);
+ phy_write(mii_info, MII_CIS8201_EXT_CON1,
+ MII_CIS8201_EXTCON1_INIT);
+
+ return 0;
+}
+
+static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+ phy_read(mii_info, MII_CIS8201_ISTAT);
+
+ return 0;
+}
+
+static int cis820x_config_intr(struct gfar_mii_info *mii_info)
+{
+ if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
+ phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+ else
+ phy_write(mii_info, MII_CIS8201_IMASK, 0);
+
+ return 0;
+}
+
+#define DM9161_DELAY 10
+
+static int dm9161_read_status(struct gfar_mii_info *mii_info)
+{
+ u16 status;
+ int err;
+
+ /* Update the link, but return if there
+ * was an error */
+ err = genmii_update_link(mii_info);
+ if (err)
+ return err;
+
+ /* If the link is up, read the speed and duplex */
+ /* If we aren't autonegotiating, assume speeds
+ * are as set */
+ if (mii_info->autoneg && mii_info->link) {
+ status = phy_read(mii_info, MII_DM9161_SCSR);
+ if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
+ mii_info->speed = SPEED_100;
+ else
+ mii_info->speed = SPEED_10;
+
+ if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
+ mii_info->duplex = DUPLEX_FULL;
+ else
+ mii_info->duplex = DUPLEX_HALF;
+ }
+
+ return 0;
+}
+
+
+static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
+{
+ struct dm9161_private *priv = mii_info->priv;
+
+ if(0 == priv->resetdone)
+ return -EAGAIN;
+
+ return 0;
+}
+
+static void dm9161_timer(unsigned long data)
+{
+ struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
+ struct dm9161_private *priv = mii_info->priv;
+ u16 status = phy_read(mii_info, MII_BMSR);
+
+ if (status & BMSR_ANEGCOMPLETE) {
+ priv->resetdone = 1;
+ } else
+ mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+}
+
+static int dm9161_init(struct gfar_mii_info *mii_info)
+{
+ struct dm9161_private *priv;
+
+ /* Allocate the private data structure */
+ priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
+
+ if (NULL == priv)
+ return -ENOMEM;
+
+ mii_info->priv = priv;
+
+ /* Reset is not done yet */
+ priv->resetdone = 0;
+
+ /* Isolate the PHY */
+ phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
+
+ /* Do not bypass the scrambler/descrambler */
+ phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+
+ /* Clear 10BTCSR to default */
+ phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+ /* Reconnect the PHY, and enable Autonegotiation */
+ phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
+
+ /* Start a timer for DM9161_DELAY seconds to wait
+ * for the PHY to be ready */
+ init_timer(&priv->timer);
+ priv->timer.function = &dm9161_timer;
+ priv->timer.data = (unsigned long) mii_info;
+ mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+
+ return 0;
+}
+
+static void dm9161_close(struct gfar_mii_info *mii_info)
+{
+ struct dm9161_private *priv = mii_info->priv;
+
+ del_timer_sync(&priv->timer);
+ kfree(priv);
+}
+
+#if 0
+static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+ phy_read(mii_info, MII_DM9161_INTR);
+
+ return 0;
+}
+#endif
+
+/* Cicada 820x */
+static struct phy_info phy_info_cis820x = {
+ 0x000fc440,
+ "Cicada Cis8204",
+ 0x000fffc0,
+ .features = MII_GBIT_FEATURES,
+ .init = &cis820x_init,
+ .config_aneg = &gbit_config_aneg,
+ .read_status = &cis820x_read_status,
+ .ack_interrupt = &cis820x_ack_interrupt,
+ .config_intr = &cis820x_config_intr,
+};
+
+static struct phy_info phy_info_dm9161 = {
+ .phy_id = 0x0181b880,
+ .name = "Davicom DM9161E",
+ .phy_id_mask = 0x0ffffff0,
+ .init = dm9161_init,
+ .config_aneg = dm9161_config_aneg,
+ .read_status = dm9161_read_status,
+ .close = dm9161_close,
+};
+
+static struct phy_info phy_info_marvell = {
+ .phy_id = 0x01410c00,
+ .phy_id_mask = 0xffffff00,
+ .name = "Marvell 88E1101/88E1111",
+ .features = MII_GBIT_FEATURES,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &marvell_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+};
+
+static struct phy_info phy_info_genmii= {
+ .phy_id = 0x00000000,
+ .phy_id_mask = 0x00000000,
+ .name = "Generic MII",
+ .features = MII_BASIC_FEATURES,
+ .config_aneg = genmii_config_aneg,
+ .read_status = genmii_read_status,
+};
+
+static struct phy_info *phy_info[] = {
+ &phy_info_cis820x,
+ &phy_info_marvell,
+ &phy_info_dm9161,
+ &phy_info_genmii,
+ NULL
+};
+
+u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
+{
+ u16 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mii_info->mdio_lock, flags);
+ retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+ spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+ return retval;
+}
+
+void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mii_info->mdio_lock, flags);
+ mii_info->mdio_write(mii_info->dev,
+ mii_info->mii_id,
+ regnum, val);
+ spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
+
+/* Use the PHY ID registers to determine what type of PHY is attached
+ * to device dev. return a struct phy_info structure describing that PHY
+ */
+struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
+{
+ u16 phy_reg;
+ u32 phy_ID;
+ int i;
+ struct phy_info *theInfo = NULL;
+ struct net_device *dev = mii_info->dev;
+
+ /* Grab the bits from PHYIR1, and put them in the upper half */
+ phy_reg = phy_read(mii_info, MII_PHYSID1);
+ phy_ID = (phy_reg & 0xffff) << 16;
+
+ /* Grab the bits from PHYIR2, and put them in the lower half */
+ phy_reg = phy_read(mii_info, MII_PHYSID2);
+ phy_ID |= (phy_reg & 0xffff);
+
+ /* loop through all the known PHY types, and find one that */
+ /* matches the ID we read from the PHY. */
+ for (i = 0; phy_info[i]; i++)
+ if (phy_info[i]->phy_id ==
+ (phy_ID & phy_info[i]->phy_id_mask)) {
+ theInfo = phy_info[i];
+ break;
+ }
+
+ /* This shouldn't happen, as we have generic PHY support */
+ if (theInfo == NULL) {
+ printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
+ return NULL;
+ } else {
+ printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
+ phy_ID);
+ }
+
+ return theInfo;
+}
diff --git a/trunk/drivers/net/gianfar_phy.h b/trunk/drivers/net/gianfar_phy.h
new file mode 100644
index 000000000000..1e9b3abf1e6d
--- /dev/null
+++ b/trunk/drivers/net/gianfar_phy.h
@@ -0,0 +1,213 @@
+/*
+ * drivers/net/gianfar_phy.h
+ *
+ * Gianfar Ethernet Driver -- PHY handling
+ * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, 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.
+ *
+ */
+#ifndef __GIANFAR_PHY_H
+#define __GIANFAR_PHY_H
+
+#define MII_end ((u32)-2)
+#define MII_read ((u32)-1)
+
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_NOTVALID 0x00000004
+
+#define GFAR_AN_TIMEOUT 2000
+
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL 0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1 0x17
+#define MII_CIS8201_EXTCON1_INIT 0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK 0x19
+#define MII_CIS8201_IMASK_IEN 0x8000
+#define MII_CIS8201_IMASK_SPEED 0x4000
+#define MII_CIS8201_IMASK_LINK 0x2000
+#define MII_CIS8201_IMASK_DUPLEX 0x1000
+#define MII_CIS8201_IMASK_MASK 0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT 0x1a
+#define MII_CIS8201_ISTAT_STATUS 0x8000
+#define MII_CIS8201_ISTAT_SPEED 0x4000
+#define MII_CIS8201_ISTAT_LINK 0x2000
+#define MII_CIS8201_ISTAT_DUPLEX 0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT 0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
+#define MII_CIS8201_AUXCONSTAT_100 0x0008
+
+/* 88E1011 PHY Status Register */
+#define MII_M1011_PHY_SPEC_STATUS 0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
+#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
+
+#define MII_M1011_IEVENT 0x13
+#define MII_M1011_IEVENT_CLEAR 0x0000
+
+#define MII_M1011_IMASK 0x12
+#define MII_M1011_IMASK_INIT 0x6400
+#define MII_M1011_IMASK_CLEAR 0x0000
+
+#define MII_DM9161_SCR 0x10
+#define MII_DM9161_SCR_INIT 0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MII_DM9161_SCSR 0x11
+#define MII_DM9161_SCSR_100F 0x8000
+#define MII_DM9161_SCSR_100H 0x4000
+#define MII_DM9161_SCSR_10F 0x2000
+#define MII_DM9161_SCSR_10H 0x1000
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR 0x15
+#define MII_DM9161_INTR_PEND 0x8000
+#define MII_DM9161_INTR_DPLX_MASK 0x0800
+#define MII_DM9161_INTR_SPD_MASK 0x0400
+#define MII_DM9161_INTR_LINK_MASK 0x0200
+#define MII_DM9161_INTR_MASK 0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
+#define MII_DM9161_INTR_SPD_CHANGE 0x0008
+#define MII_DM9161_INTR_LINK_CHANGE 0x0004
+#define MII_DM9161_INTR_INIT 0x0000
+#define MII_DM9161_INTR_STOP \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR 0x12
+#define MII_DM9161_10BTCSR_INIT 0x7800
+
+#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
+ SUPPORTED_10baseT_Full | \
+ SUPPORTED_100baseT_Half | \
+ SUPPORTED_100baseT_Full | \
+ SUPPORTED_Autoneg | \
+ SUPPORTED_TP | \
+ SUPPORTED_MII)
+
+#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
+ SUPPORTED_1000baseT_Half | \
+ SUPPORTED_1000baseT_Full)
+
+#define MII_READ_COMMAND 0x00000001
+
+#define MII_INTERRUPT_DISABLED 0x0
+#define MII_INTERRUPT_ENABLED 0x1
+/* Taken from mii_if_info and sungem_phy.h */
+struct gfar_mii_info {
+ /* Information about the PHY type */
+ /* And management functions */
+ struct phy_info *phyinfo;
+
+ /* forced speed & duplex (no autoneg)
+ * partner speed & duplex & pause (autoneg)
+ */
+ int speed;
+ int duplex;
+ int pause;
+
+ /* The most recently read link state */
+ int link;
+
+ /* Enabled Interrupts */
+ u32 interrupts;
+
+ u32 advertising;
+ int autoneg;
+ int mii_id;
+
+ /* private data pointer */
+ /* For use by PHYs to maintain extra state */
+ void *priv;
+
+ /* Provided by host chip */
+ struct net_device *dev;
+
+ /* A lock to ensure that only one thing can read/write
+ * the MDIO bus at a time */
+ spinlock_t mdio_lock;
+
+ /* Provided by ethernet driver */
+ int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
+ void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY. During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is. The 32-bit result
+ * gotten from the PHY will be ANDed with phy_id_mask to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ * There are 6 commands which take a gfar_mii_info structure.
+ * Each PHY must declare config_aneg, and read_status.
+ */
+struct phy_info {
+ u32 phy_id;
+ char *name;
+ unsigned int phy_id_mask;
+ u32 features;
+
+ /* Called to initialize the PHY */
+ int (*init)(struct gfar_mii_info *mii_info);
+
+ /* Called to suspend the PHY for power */
+ int (*suspend)(struct gfar_mii_info *mii_info);
+
+ /* Reconfigures autonegotiation (or disables it) */
+ int (*config_aneg)(struct gfar_mii_info *mii_info);
+
+ /* Determines the negotiated speed and duplex */
+ int (*read_status)(struct gfar_mii_info *mii_info);
+
+ /* Clears any pending interrupts */
+ int (*ack_interrupt)(struct gfar_mii_info *mii_info);
+
+ /* Enables or disables interrupts */
+ int (*config_intr)(struct gfar_mii_info *mii_info);
+
+ /* Clears up any memory if needed */
+ void (*close)(struct gfar_mii_info *mii_info);
+};
+
+struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
+void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
+void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
+
+struct dm9161_private {
+ struct timer_list timer;
+ int resetdone;
+};
+
+#endif /* GIANFAR_PHY_H */
diff --git a/trunk/drivers/net/hamradio/Kconfig b/trunk/drivers/net/hamradio/Kconfig
index 896aa02000d7..de087cd609d9 100644
--- a/trunk/drivers/net/hamradio/Kconfig
+++ b/trunk/drivers/net/hamradio/Kconfig
@@ -1,7 +1,6 @@
config MKISS
tristate "Serial port KISS driver"
depends on AX25
- select CRC16
---help---
KISS is a protocol used for the exchange of data between a computer
and a Terminal Node Controller (a small embedded system commonly
diff --git a/trunk/drivers/net/hamradio/bpqether.c b/trunk/drivers/net/hamradio/bpqether.c
index cb43a9d28774..1756f0ed54cc 100644
--- a/trunk/drivers/net/hamradio/bpqether.c
+++ b/trunk/drivers/net/hamradio/bpqether.c
@@ -144,7 +144,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
{
struct bpqdev *bpq;
- list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
+ list_for_each_entry(bpq, &bpq_devices, bpq_list) {
if (bpq->ethdev == dev)
return bpq->axdev;
}
@@ -399,7 +399,7 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
if (*pos == 0)
return SEQ_START_TOKEN;
- list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {
+ list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
if (i == *pos)
return bpqdev;
}
@@ -418,7 +418,7 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
p = ((struct bpqdev *)v)->bpq_list.next;
return (p == &bpq_devices) ? NULL
- : rcu_dereference(list_entry(p, struct bpqdev, bpq_list));
+ : list_entry(p, struct bpqdev, bpq_list);
}
static void bpq_seq_stop(struct seq_file *seq, void *v)
@@ -561,6 +561,8 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
+ rcu_read_lock();
+
switch (event) {
case NETDEV_UP: /* new ethernet device -> new BPQ interface */
if (bpq_get_ax25_dev(dev) == NULL)
@@ -579,6 +581,7 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
default:
break;
}
+ rcu_read_unlock();
return NOTIFY_DONE;
}
diff --git a/trunk/drivers/net/hamradio/mkiss.c b/trunk/drivers/net/hamradio/mkiss.c
index 85d6dc005be0..d9fe64b46f4b 100644
--- a/trunk/drivers/net/hamradio/mkiss.c
+++ b/trunk/drivers/net/hamradio/mkiss.c
@@ -14,14 +14,13 @@
*
* Copyright (C) Hans Alblas PE1AYX
* Copyright (C) 2004, 05 Ralf Baechle DL5RB
- * Copyright (C) 2004, 05 Thomas Osterried DL9SAU
*/
+
#include
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -40,6 +39,11 @@
#include
+#ifdef CONFIG_INET
+#include
+#include
+#endif
+
#define AX_MTU 236
/* SLIP/KISS protocol characters. */
@@ -76,13 +80,9 @@ struct mkiss {
int mode;
int crcmode; /* MW: for FlexNet, SMACK etc. */
- int crcauto; /* CRC auto mode */
-
-#define CRC_MODE_NONE 0
-#define CRC_MODE_FLEX 1
-#define CRC_MODE_SMACK 2
-#define CRC_MODE_FLEX_TEST 3
-#define CRC_MODE_SMACK_TEST 4
+#define CRC_MODE_NONE 0
+#define CRC_MODE_FLEX 1
+#define CRC_MODE_SMACK 2
atomic_t refcnt;
struct semaphore dead_sem;
@@ -151,21 +151,6 @@ static int check_crc_flex(unsigned char *cp, int size)
return 0;
}
-static int check_crc_16(unsigned char *cp, int size)
-{
- unsigned short crc = 0x0000;
-
- if (size < 3)
- return -1;
-
- crc = crc16(0, cp, size);
-
- if (crc != 0x0000)
- return -1;
-
- return 0;
-}
-
/*
* Standard encapsulation
*/
@@ -252,42 +237,19 @@ static void ax_bump(struct mkiss *ax)
spin_lock_bh(&ax->buflock);
if (ax->rbuff[0] > 0x0f) {
- if (ax->rbuff[0] & 0x80) {
- if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
- ax->stats.rx_errors++;
- spin_unlock_bh(&ax->buflock);
-
- return;
- }
- if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
- printk(KERN_INFO
- "mkiss: %s: Switchting to crc-smack\n",
- ax->dev->name);
- ax->crcmode = CRC_MODE_SMACK;
- }
- ax->rcount -= 2;
- *ax->rbuff &= ~0x80;
- } else if (ax->rbuff[0] & 0x20) {
+ if (ax->rbuff[0] & 0x20) {
+ ax->crcmode = CRC_MODE_FLEX;
if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
- ax->stats.rx_errors++;
- spin_unlock_bh(&ax->buflock);
+ ax->stats.rx_errors++;
return;
}
- if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
- printk(KERN_INFO
- "mkiss: %s: Switchting to crc-flexnet\n",
- ax->dev->name);
- ax->crcmode = CRC_MODE_FLEX;
- }
ax->rcount -= 2;
-
- /*
- * dl9sau bugfix: the trailling two bytes flexnet crc
- * will not be passed to the kernel. thus we have to
- * correct the kissparm signature, because it indicates
- * a crc but there's none
+ /* dl9sau bugfix: the trailling two bytes flexnet crc
+ * will not be passed to the kernel. thus we have
+ * to correct the kissparm signature, because it
+ * indicates a crc but there's none
*/
- *ax->rbuff &= ~0x20;
+ *ax->rbuff &= ~0x20;
}
}
spin_unlock_bh(&ax->buflock);
@@ -455,69 +417,20 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
p = icp;
spin_lock_bh(&ax->buflock);
- if ((*p & 0x0f) != 0) {
- /* Configuration Command (kissparms(1).
- * Protocol spec says: never append CRC.
- * This fixes a very old bug in the linux
- * kiss driver. -- dl9sau */
- switch (*p & 0xff) {
- case 0x85:
- /* command from userspace especially for us,
- * not for delivery to the tnc */
- if (len > 1) {
- int cmd = (p[1] & 0xff);
- switch(cmd) {
- case 3:
- ax->crcmode = CRC_MODE_SMACK;
- break;
- case 2:
- ax->crcmode = CRC_MODE_FLEX;
- break;
- case 1:
- ax->crcmode = CRC_MODE_NONE;
- break;
- case 0:
- default:
- ax->crcmode = CRC_MODE_SMACK_TEST;
- cmd = 0;
- }
- ax->crcauto = (cmd ? 0 : 1);
- printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
- }
- spin_unlock_bh(&ax->buflock);
- netif_start_queue(dev);
+ switch (ax->crcmode) {
+ unsigned short crc;
- return;
- default:
- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
- }
- } else {
- unsigned short crc;
- switch (ax->crcmode) {
- case CRC_MODE_SMACK_TEST:
- ax->crcmode = CRC_MODE_FLEX_TEST;
- printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
- // fall through
- case CRC_MODE_SMACK:
- *p |= 0x80;
- crc = swab16(crc16(0, p, len));
- count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
- break;
- case CRC_MODE_FLEX_TEST:
- ax->crcmode = CRC_MODE_NONE;
- printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
- // fall through
- case CRC_MODE_FLEX:
- *p |= 0x20;
- crc = calc_crc_flex(p, len);
- count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
- break;
-
- default:
- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
- }
- }
+ case CRC_MODE_FLEX:
+ *p |= 0x20;
+ crc = calc_crc_flex(p, len);
+ count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+ break;
+ default:
+ count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+ break;
+ }
+
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
ax->stats.tx_packets++;
@@ -526,6 +439,8 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
ax->dev->trans_start = jiffies;
ax->xleft = count - actual;
ax->xhead = ax->xbuff + actual;
+
+ spin_unlock_bh(&ax->buflock);
}
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
@@ -707,7 +622,7 @@ static void ax_setup(struct net_device *dev)
* best way to fix this is to use a rwlock in the tty struct, but for now we
* use a single global rwlock for all ttys in ppp line discipline.
*/
-static DEFINE_RWLOCK(disc_data_lock);
+static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
static struct mkiss *mkiss_get(struct tty_struct *tty)
{
@@ -728,8 +643,6 @@ static void mkiss_put(struct mkiss *ax)
up(&ax->dead_sem);
}
-static int crc_force = 0; /* Can be overridden with insmod */
-
static int mkiss_open(struct tty_struct *tty)
{
struct net_device *dev;
@@ -769,33 +682,6 @@ static int mkiss_open(struct tty_struct *tty)
if (register_netdev(dev))
goto out_free_buffers;
- /* after register_netdev() - because else printk smashes the kernel */
- switch (crc_force) {
- case 3:
- ax->crcmode = CRC_MODE_SMACK;
- printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
- ax->dev->name);
- break;
- case 2:
- ax->crcmode = CRC_MODE_FLEX;
- printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
- ax->dev->name);
- break;
- case 1:
- ax->crcmode = CRC_MODE_NONE;
- printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
- ax->dev->name);
- break;
- case 0:
- /* fall through */
- default:
- crc_force = 0;
- printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
- ax->dev->name);
- ax->crcmode = CRC_MODE_SMACK_TEST;
- }
- ax->crcauto = (crc_force ? 0 : 1);
-
netif_start_queue(dev);
/* Done. We have linked the TTY line to a channel. */
@@ -879,6 +765,7 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
case SIOCSIFHWADDR: {
char addr[AX25_ADDR_LEN];
+printk(KERN_INFO "In SIOCSIFHWADDR");
if (copy_from_user(&addr,
(void __user *) arg, AX25_ADDR_LEN)) {
@@ -977,7 +864,6 @@ static void mkiss_write_wakeup(struct tty_struct *tty)
}
static struct tty_ldisc ax_ldisc = {
- .owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "mkiss",
.open = mkiss_open,
@@ -1018,8 +904,6 @@ static void __exit mkiss_exit_driver(void)
MODULE_AUTHOR("Ralf Baechle DL5RB ");
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
-MODULE_PARM(crc_force, "i");
-MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_AX25);
diff --git a/trunk/drivers/net/hamradio/mkiss.h b/trunk/drivers/net/hamradio/mkiss.h
new file mode 100644
index 000000000000..4ab700478598
--- /dev/null
+++ b/trunk/drivers/net/hamradio/mkiss.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+ * Defines for the Multi-KISS driver.
+ ****************************************************************************/
+
+#define AX25_MAXDEV 16 /* MAX number of AX25 channels;
+ This can be overridden with
+ insmod -oax25_maxdev=nnn */
+#define AX_MTU 236
+
+/* SLIP/KISS protocol characters. */
+#define END 0300 /* indicates end of frame */
+#define ESC 0333 /* indicates byte stuffing */
+#define ESC_END 0334 /* ESC ESC_END means END 'data' */
+#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
+
+struct ax_disp {
+ int magic;
+
+ /* Various fields. */
+ struct tty_struct *tty; /* ptr to TTY structure */
+ struct net_device *dev; /* easy for intr handling */
+
+ /* These are pointers to the malloc()ed frame buffers. */
+ unsigned char *rbuff; /* receiver buffer */
+ int rcount; /* received chars counter */
+ unsigned char *xbuff; /* transmitter buffer */
+ unsigned char *xhead; /* pointer to next byte to XMIT */
+ int xleft; /* bytes left in XMIT queue */
+
+ /* SLIP interface statistics. */
+ unsigned long rx_packets; /* inbound frames counter */
+ unsigned long tx_packets; /* outbound frames counter */
+ unsigned long rx_bytes; /* inbound bytes counter */
+ unsigned long tx_bytes; /* outbound bytes counter */
+ unsigned long rx_errors; /* Parity, etc. errors */
+ unsigned long tx_errors; /* Planned stuff */
+ unsigned long rx_dropped; /* No memory for skb */
+ unsigned long tx_dropped; /* When MTU change */
+ unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
+
+ /* Detailed SLIP statistics. */
+ int mtu; /* Our mtu (to spot changes!) */
+ int buffsize; /* Max buffers sizes */
+
+
+ unsigned long flags; /* Flag values/ mode etc */
+ /* long req'd: used by set_bit --RR */
+#define AXF_INUSE 0 /* Channel in use */
+#define AXF_ESCAPE 1 /* ESC received */
+#define AXF_ERROR 2 /* Parity, etc. error */
+#define AXF_KEEPTEST 3 /* Keepalive test flag */
+#define AXF_OUTWAIT 4 /* is outpacket was flag */
+
+ int mode;
+ int crcmode; /* MW: for FlexNet, SMACK etc. */
+#define CRC_MODE_NONE 0
+#define CRC_MODE_FLEX 1
+#define CRC_MODE_SMACK 2
+ spinlock_t buflock; /* lock for rbuf and xbuf */
+};
+
+#define AX25_MAGIC 0x5316
diff --git a/trunk/drivers/net/hp100.c b/trunk/drivers/net/hp100.c
index b71fab6e34f4..cf0ac6fda1a1 100644
--- a/trunk/drivers/net/hp100.c
+++ b/trunk/drivers/net/hp100.c
@@ -2517,8 +2517,10 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
break;
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
if (time_after_eq(jiffies, time)) /* no signal->no logout */
@@ -2534,8 +2536,10 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
break;
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
#ifdef HP100_DEBUG
@@ -2573,8 +2577,10 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
break;
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
hp100_orb(HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */
@@ -2585,8 +2591,10 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
break;
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
if (time_before_eq(time, jiffies)) {
@@ -2598,8 +2606,10 @@ static int hp100_down_vg_link(struct net_device *dev)
time = jiffies + (2 * HZ); /* This seems to take a while.... */
do {
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
return 0;
@@ -2649,8 +2659,10 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
do {
if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
break;
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
/* Start an addressed training and optionally request promiscuous port */
@@ -2685,8 +2697,10 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
do {
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
break;
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_before(jiffies, time));
if (time_after_eq(jiffies, time)) {
@@ -2709,8 +2723,10 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
#endif
break;
}
- if (!in_interrupt())
- schedule_timeout_interruptible(1);
+ if (!in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
} while (time_after(time, jiffies));
}
diff --git a/trunk/drivers/net/irda/stir4200.c b/trunk/drivers/net/irda/stir4200.c
index 3961a754e920..15f207323d97 100644
--- a/trunk/drivers/net/irda/stir4200.c
+++ b/trunk/drivers/net/irda/stir4200.c
@@ -678,9 +678,10 @@ static void turnaround_delay(const struct stir_cb *stir, long us)
return;
ticks = us / (1000000 / HZ);
- if (ticks > 0)
- schedule_timeout_interruptible(1 + ticks);
- else
+ if (ticks > 0) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1 + ticks);
+ } else
udelay(us);
}
diff --git a/trunk/drivers/net/ixgb/ixgb_ethtool.c b/trunk/drivers/net/ixgb/ixgb_ethtool.c
index 04e47189d830..9d026ed77ddd 100644
--- a/trunk/drivers/net/ixgb/ixgb_ethtool.c
+++ b/trunk/drivers/net/ixgb/ixgb_ethtool.c
@@ -645,10 +645,11 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
- if (data)
- schedule_timeout_interruptible(data * HZ);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if(data)
+ schedule_timeout(data * HZ);
else
- schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+ schedule_timeout(MAX_SCHEDULE_TIMEOUT);
del_timer_sync(&adapter->blink_timer);
ixgb_led_off(&adapter->hw);
@@ -722,7 +723,6 @@ struct ethtool_ops ixgb_ethtool_ops = {
.phys_id = ixgb_phys_id,
.get_stats_count = ixgb_get_stats_count,
.get_ethtool_stats = ixgb_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/trunk/drivers/net/ixgb/ixgb_main.c b/trunk/drivers/net/ixgb/ixgb_main.c
index 176680cb153e..89d6d69be382 100644
--- a/trunk/drivers/net/ixgb/ixgb_main.c
+++ b/trunk/drivers/net/ixgb/ixgb_main.c
@@ -460,9 +460,8 @@ ixgb_probe(struct pci_dev *pdev,
}
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
- memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->perm_addr)) {
+ if(!is_valid_ether_addr(netdev->dev_addr)) {
err = -EIO;
goto err_eeprom;
}
diff --git a/trunk/drivers/net/lance.c b/trunk/drivers/net/lance.c
index 1d75ca0bb939..b4929beb33b2 100644
--- a/trunk/drivers/net/lance.c
+++ b/trunk/drivers/net/lance.c
@@ -298,7 +298,7 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_
static unsigned char lance_need_isa_bounce_buffers = 1;
static int lance_open(struct net_device *dev);
-static void lance_init_ring(struct net_device *dev, gfp_t mode);
+static void lance_init_ring(struct net_device *dev, int mode);
static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int lance_rx(struct net_device *dev);
static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -846,7 +846,7 @@ lance_purge_ring(struct net_device *dev)
/* Initialize the LANCE Rx and Tx rings. */
static void
-lance_init_ring(struct net_device *dev, gfp_t gfp)
+lance_init_ring(struct net_device *dev, int gfp)
{
struct lance_private *lp = dev->priv;
int i;
diff --git a/trunk/drivers/net/lne390.c b/trunk/drivers/net/lne390.c
index 309d254842cf..27f0d8ac4c40 100644
--- a/trunk/drivers/net/lne390.c
+++ b/trunk/drivers/net/lne390.c
@@ -298,7 +298,7 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
return 0;
unmap:
if (ei_status.reg0)
- iounmap(ei_status.mem);
+ iounmap((void *)dev->mem_start);
cleanup:
free_irq(dev->irq, dev);
return ret;
diff --git a/trunk/drivers/net/mii.c b/trunk/drivers/net/mii.c
index e42aa797f08b..c33cb3dc942b 100644
--- a/trunk/drivers/net/mii.c
+++ b/trunk/drivers/net/mii.c
@@ -207,20 +207,6 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
return 0;
}
-int mii_check_gmii_support(struct mii_if_info *mii)
-{
- int reg;
-
- reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
- if (reg & BMSR_ESTATEN) {
- reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
- if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
- return 1;
- }
-
- return 0;
-}
-
int mii_link_ok (struct mii_if_info *mii)
{
/* first, a dummy read, needed to latch some MII phys */
@@ -408,6 +394,5 @@ EXPORT_SYMBOL(mii_ethtool_gset);
EXPORT_SYMBOL(mii_ethtool_sset);
EXPORT_SYMBOL(mii_check_link);
EXPORT_SYMBOL(mii_check_media);
-EXPORT_SYMBOL(mii_check_gmii_support);
EXPORT_SYMBOL(generic_mii_ioctl);
diff --git a/trunk/drivers/net/mipsnet.c b/trunk/drivers/net/mipsnet.c
deleted file mode 100644
index f79f7ee72ab8..000000000000
--- a/trunk/drivers/net/mipsnet.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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.
- */
-
-#define DEBUG
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mipsnet.h" /* actual device IO mapping */
-
-#define MIPSNET_VERSION "2005-06-20"
-
-#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
-
-struct mipsnet_priv {
- struct net_device_stats stats;
-};
-
-static struct platform_device *mips_plat_dev;
-
-static char mipsnet_string[] = "mipsnet";
-
-/*
- * Copy data from the MIPSNET rx data port
- */
-static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
- int len)
-{
- uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
- if (available_len < len)
- return -EFAULT;
-
- for (; len > 0; len--, kdata++) {
- *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
- }
-
- return inl(mipsnet_reg_address(dev, rxDataCount));
-}
-
-static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
- struct sk_buff *skb)
-{
- int count_to_go = skb->len;
- char *buf_ptr = skb->data;
- struct mipsnet_priv *mp = netdev_priv(dev);
-
- pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
- dev->name, __FUNCTION__, skb->len);
-
- outl(skb->len, mipsnet_reg_address(dev, txDataCount));
-
- pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
- dev->name, __FUNCTION__, skb->len);
-
- for (; count_to_go; buf_ptr++, count_to_go--) {
- outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
- }
-
- mp->stats.tx_packets++;
- mp->stats.tx_bytes += skb->len;
-
- return skb->len;
-}
-
-static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- pr_debug("%s:%s(): transmitting %d bytes\n",
- dev->name, __FUNCTION__, skb->len);
-
- /* Only one packet at a time. Once TXDONE interrupt is serviced, the
- * queue will be restarted.
- */
- netif_stop_queue(dev);
- mipsnet_put_todevice(dev, skb);
-
- return 0;
-}
-
-static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
-{
- struct sk_buff *skb;
- size_t len = count;
- struct mipsnet_priv *mp = netdev_priv(dev);
-
- if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
- mp->stats.rx_dropped++;
- return -ENOMEM;
- }
-
- skb_reserve(skb, 2);
- if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
- return -EFAULT;
-
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
-
- pr_debug("%s:%s(): pushing RXed data to kernel\n",
- dev->name, __FUNCTION__);
- netif_rx(skb);
-
- mp->stats.rx_packets++;
- mp->stats.rx_bytes += len;
-
- return count;
-}
-
-static irqreturn_t
-mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = dev_id;
-
- irqreturn_t retval = IRQ_NONE;
- uint64_t interruptFlags;
-
- if (irq == dev->irq) {
- pr_debug("%s:%s(): irq %d for device\n",
- dev->name, __FUNCTION__, irq);
-
- retval = IRQ_HANDLED;
-
- interruptFlags =
- inl(mipsnet_reg_address(dev, interruptControl));
- pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
- __FUNCTION__, interruptFlags);
-
- if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
- pr_debug("%s:%s(): got TXDone\n",
- dev->name, __FUNCTION__);
- outl(MIPSNET_INTCTL_TXDONE,
- mipsnet_reg_address(dev, interruptControl));
- // only one packet at a time, we are done.
- netif_wake_queue(dev);
- } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
- pr_debug("%s:%s(): got RX data\n",
- dev->name, __FUNCTION__);
- mipsnet_get_fromdev(dev,
- inl(mipsnet_reg_address(dev, rxDataCount)));
- pr_debug("%s:%s(): clearing RX int\n",
- dev->name, __FUNCTION__);
- outl(MIPSNET_INTCTL_RXDONE,
- mipsnet_reg_address(dev, interruptControl));
-
- } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
- pr_debug("%s:%s(): got test interrupt\n",
- dev->name, __FUNCTION__);
- // TESTBIT is cleared on read.
- // And takes effect after a write with 0
- outl(0, mipsnet_reg_address(dev, interruptControl));
- } else {
- pr_debug("%s:%s(): no valid fags 0x%016llx\n",
- dev->name, __FUNCTION__, interruptFlags);
- // Maybe shared IRQ, just ignore, no clearing.
- retval = IRQ_NONE;
- }
-
- } else {
- printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
- dev->name, __FUNCTION__, irq);
- retval = IRQ_NONE;
- }
- return retval;
-} //mipsnet_interrupt()
-
-static int mipsnet_open(struct net_device *dev)
-{
- int err;
- pr_debug("%s: mipsnet_open\n", dev->name);
-
- err = request_irq(dev->irq, &mipsnet_interrupt,
- SA_SHIRQ, dev->name, (void *) dev);
-
- if (err) {
- pr_debug("%s: %s(): can't get irq %d\n",
- dev->name, __FUNCTION__, dev->irq);
- release_region(dev->base_addr, MIPSNET_IO_EXTENT);
- return err;
- }
-
- pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
- dev->name, __FUNCTION__, dev->base_addr, dev->irq);
-
-
- netif_start_queue(dev);
-
- // test interrupt handler
- outl(MIPSNET_INTCTL_TESTBIT,
- mipsnet_reg_address(dev, interruptControl));
-
-
- return 0;
-}
-
-static int mipsnet_close(struct net_device *dev)
-{
- pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
- netif_stop_queue(dev);
- return 0;
-}
-
-static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
-{
- struct mipsnet_priv *mp = netdev_priv(dev);
-
- return &mp->stats;
-}
-
-static void mipsnet_set_mclist(struct net_device *dev)
-{
- // we don't do anything
- return;
-}
-
-static int __init mipsnet_probe(struct device *dev)
-{
- struct net_device *netdev;
- int err;
-
- netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
- if (!netdev) {
- err = -ENOMEM;
- goto out;
- }
-
- dev_set_drvdata(dev, netdev);
-
- netdev->open = mipsnet_open;
- netdev->stop = mipsnet_close;
- netdev->hard_start_xmit = mipsnet_xmit;
- netdev->get_stats = mipsnet_get_stats;
- netdev->set_multicast_list = mipsnet_set_mclist;
-
- /*
- * TODO: probe for these or load them from PARAM
- */
- netdev->base_addr = 0x4200;
- netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
- inl(mipsnet_reg_address(netdev, interruptInfo));
-
- // Get the io region now, get irq on open()
- if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
- pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
- "for dev is not availble.\n", netdev->name,
- __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
- err = -EBUSY;
- goto out_free_netdev;
- }
-
- /*
- * Lacking any better mechanism to allocate a MAC address we use a
- * random one ...
- */
- random_ether_addr(netdev->dev_addr);
-
- err = register_netdev(netdev);
- if (err) {
- printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
- goto out_free_region;
- }
-
- return 0;
-
-out_free_region:
- release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
-
-out_free_netdev:
- free_netdev(netdev);
-
-out:
- return err;
-}
-
-static int __devexit mipsnet_device_remove(struct device *device)
-{
- struct net_device *dev = dev_get_drvdata(device);
-
- unregister_netdev(dev);
- release_region(dev->base_addr, MIPSNET_IO_EXTENT);
- free_netdev(dev);
- dev_set_drvdata(device, NULL);
-
- return 0;
-}
-
-static struct device_driver mipsnet_driver = {
- .name = mipsnet_string,
- .bus = &platform_bus_type,
- .probe = mipsnet_probe,
- .remove = __devexit_p(mipsnet_device_remove),
-};
-
-static void mipsnet_platform_release(struct device *device)
-{
- struct platform_device *pldev;
-
- /* free device */
- pldev = to_platform_device(device);
- kfree(pldev);
-}
-
-static int __init mipsnet_init_module(void)
-{
- struct platform_device *pldev;
- int err;
-
- printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
- "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
-
- if (driver_register(&mipsnet_driver)) {
- printk(KERN_ERR "Driver registration failed\n");
- err = -ENODEV;
- goto out;
- }
-
- if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
- err = -ENOMEM;
- goto out_unregister_driver;
- }
-
- memset (pldev, 0, sizeof (*pldev));
- pldev->name = mipsnet_string;
- pldev->id = 0;
- pldev->dev.release = mipsnet_platform_release;
-
- if (platform_device_register(pldev)) {
- err = -ENODEV;
- goto out_free_pldev;
- }
-
- if (!pldev->dev.driver) {
- /*
- * The driver was not bound to this device, there was
- * no hardware at this address. Unregister it, as the
- * release fuction will take care of freeing the
- * allocated structure
- */
- platform_device_unregister (pldev);
- }
-
- mips_plat_dev = pldev;
-
- return 0;
-
-out_free_pldev:
- kfree(pldev);
-
-out_unregister_driver:
- driver_unregister(&mipsnet_driver);
-out:
- return err;
-}
-
-static void __exit mipsnet_exit_module(void)
-{
- pr_debug("MIPSNet Ethernet driver exiting\n");
-
- driver_unregister(&mipsnet_driver);
-}
-
-module_init(mipsnet_init_module);
-module_exit(mipsnet_exit_module);
diff --git a/trunk/drivers/net/mipsnet.h b/trunk/drivers/net/mipsnet.h
deleted file mode 100644
index 878535953cb1..000000000000
--- a/trunk/drivers/net/mipsnet.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//
-//
-// Unpublished work (c) MIPS Technologies, Inc. All rights reserved.
-// Unpublished rights reserved under the copyright laws of the U.S.A. and
-// other countries.
-//
-// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
-// FOR INTERNAL USE ONLY.
-//
-// Under no circumstances (contract or otherwise) may this information be
-// disclosed to, or copied, modified or used by anyone other than employees
-// or contractors of MIPS Technologies having a need to know.
-//
-//
-//++
-// File: MIPS_Net.h
-//
-// Description:
-// The definition of the emulated MIPSNET device's interface.
-//
-// Notes: This include file needs to work from a Linux device drivers.
-//
-//--
-//
-
-#ifndef __MIPSNET_H
-#define __MIPSNET_H
-
-/*
- * Id of this Net device, as seen by the core.
- */
-#define MIPS_NET_DEV_ID ((uint64_t) \
- ((uint64_t)'M'<< 0)| \
- ((uint64_t)'I'<< 8)| \
- ((uint64_t)'P'<<16)| \
- ((uint64_t)'S'<<24)| \
- ((uint64_t)'N'<<32)| \
- ((uint64_t)'E'<<40)| \
- ((uint64_t)'T'<<48)| \
- ((uint64_t)'0'<<56))
-
-/*
- * Net status/control block as seen by sw in the core.
- * (Why not use bit fields? can't be bothered with cross-platform struct
- * packing.)
- */
-typedef struct _net_control_block {
- /// dev info for probing
- /// reads as MIPSNET%d where %d is some form of version
- uint64_t devId; /*0x00 */
-
- /*
- * read only busy flag.
- * Set and cleared by the Net Device to indicate that an rx or a tx
- * is in progress.
- */
- uint32_t busy; /*0x08 */
-
- /*
- * Set by the Net Device.
- * The device will set it once data has been received.
- * The value is the number of bytes that should be read from
- * rxDataBuffer. The value will decrease till 0 until all the data
- * from rxDataBuffer has been read.
- */
- uint32_t rxDataCount; /*0x0c */
-#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
-
- /*
- * Settable from the MIPS core, cleared by the Net Device.
- * The core should set the number of bytes it wants to send,
- * then it should write those bytes of data to txDataBuffer.
- * The device will clear txDataCount has been processed (not necessarily sent).
- */
- uint32_t txDataCount; /*0x10 */
-
- /*
- * Interrupt control
- *
- * Used to clear the interrupted generated by this dev.
- * Write a 1 to clear the interrupt. (except bit31).
- *
- * Bit0 is set if it was a tx-done interrupt.
- * Bit1 is set when new rx-data is available.
- * Until this bit is cleared there will be no other RXs.
- *
- * Bit31 is used for testing, it clears after a read.
- * Writing 1 to this bit will cause an interrupt to be generated.
- * To clear the test interrupt, write 0 to this register.
- */
- uint32_t interruptControl; /*0x14 */
-#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0))
-#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1))
-#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31))
-#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
-
- /*
- * Readonly core-specific interrupt info for the device to signal the core.
- * The meaning of the contents of this field might change.
- */
- /*###\todo: the whole memIntf interrupt scheme is messy: the device should have
- * no control what so ever of what VPE/register set is being used.
- * The MemIntf should only expose interrupt lines, and something in the
- * config should be responsible for the line<->core/vpe bindings.
- */
- uint32_t interruptInfo; /*0x18 */
-
- /*
- * This is where the received data is read out.
- * There is more data to read until rxDataReady is 0.
- * Only 1 byte at this regs offset is used.
- */
- uint32_t rxDataBuffer; /*0x1c */
-
- /*
- * This is where the data to transmit is written.
- * Data should be written for the amount specified in the txDataCount register.
- * Only 1 byte at this regs offset is used.
- */
- uint32_t txDataBuffer; /*0x20 */
-} MIPS_T_NetControl;
-
-#define MIPSNET_IO_EXTENT 0x40 /* being generous */
-
-#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
-
-#endif /* __MIPSNET_H */
diff --git a/trunk/drivers/net/myri_sbus.c b/trunk/drivers/net/myri_sbus.c
index 6c86dca62e2a..f0996ce5c268 100644
--- a/trunk/drivers/net/myri_sbus.c
+++ b/trunk/drivers/net/myri_sbus.c
@@ -277,7 +277,7 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq)
struct recvq __iomem *rq = mp->rq;
struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
struct net_device *dev = mp->dev;
- gfp_t gfp_flags = GFP_KERNEL;
+ int gfp_flags = GFP_KERNEL;
int i;
if (from_irq || in_interrupt())
diff --git a/trunk/drivers/net/myri_sbus.h b/trunk/drivers/net/myri_sbus.h
index 47722f708a41..9391e55a5e92 100644
--- a/trunk/drivers/net/myri_sbus.h
+++ b/trunk/drivers/net/myri_sbus.h
@@ -296,7 +296,7 @@ struct myri_eth {
/* We use this to acquire receive skb's that we can DMA directly into. */
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
+static inline struct sk_buff *myri_alloc_skb(unsigned int length, int gfp_flags)
{
struct sk_buff *skb;
diff --git a/trunk/drivers/net/ne.c b/trunk/drivers/net/ne.c
index 0de8fdd2aa86..d209a1556b2e 100644
--- a/trunk/drivers/net/ne.c
+++ b/trunk/drivers/net/ne.c
@@ -54,10 +54,6 @@ static const char version2[] =
#include
#include
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
-#include
-#endif
-
#include "8390.h"
#define DRV_NAME "ne"
@@ -115,9 +111,6 @@ bad_clone_list[] __initdata = {
{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
{"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
{"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
- {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
-#endif
{"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
{NULL,}
};
@@ -233,10 +226,6 @@ struct net_device * __init ne_probe(int unit)
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
-#ifdef CONFIG_TOSHIBA_RBTX4938
- dev->base_addr = 0x07f20280;
- dev->irq = RBTX4938_RTL_8019_IRQ;
-#endif
err = do_ne_probe(dev);
if (err)
goto out;
@@ -517,10 +506,6 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
ei_status.name = name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
- wordlength = 1;
-#endif
-
#ifdef CONFIG_PLAT_OAKS32R
ei_status.word16 = 0;
#else
diff --git a/trunk/drivers/net/ne2k-pci.c b/trunk/drivers/net/ne2k-pci.c
index e531a4eedfee..f1c01ac29102 100644
--- a/trunk/drivers/net/ne2k-pci.c
+++ b/trunk/drivers/net/ne2k-pci.c
@@ -372,7 +372,6 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
dev->dev_addr[i] = SA_prom[i];
}
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
return 0;
@@ -638,7 +637,6 @@ static struct ethtool_ops ne2k_pci_ethtool_ops = {
.get_drvinfo = ne2k_pci_get_drvinfo,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
diff --git a/trunk/drivers/net/ns83820.c b/trunk/drivers/net/ns83820.c
index a3c3fc9c0d8a..e4811b42a6b7 100644
--- a/trunk/drivers/net/ns83820.c
+++ b/trunk/drivers/net/ns83820.c
@@ -1632,7 +1632,8 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
timed_out = 1;
break;
}
- schedule_timeout_uninterruptible(1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
}
if (status & fail)
diff --git a/trunk/drivers/net/pcnet32.c b/trunk/drivers/net/pcnet32.c
index 70fe81a89df9..113b68099216 100644
--- a/trunk/drivers/net/pcnet32.c
+++ b/trunk/drivers/net/pcnet32.c
@@ -22,8 +22,8 @@
*************************************************************************/
#define DRV_NAME "pcnet32"
-#define DRV_VERSION "1.31a"
-#define DRV_RELDATE "12.Sep.2005"
+#define DRV_VERSION "1.30j"
+#define DRV_RELDATE "29.04.2005"
#define PFX DRV_NAME ": "
static const char *version =
@@ -257,9 +257,6 @@ static int homepna[MAX_UNITS];
* v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
* v1.30i 28 Jun 2004 Don Fry change to use module_param.
* v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test.
- * v1.31 02 Sep 2005 Hubert WS Lin added set_ringparam().
- * v1.31a 12 Sep 2005 Hubert WS Lin set min ring size to 4
- * to allow loopback test to work unchanged.
*/
@@ -269,17 +266,17 @@ static int homepna[MAX_UNITS];
* That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
*/
#ifndef PCNET32_LOG_TX_BUFFERS
-#define PCNET32_LOG_TX_BUFFERS 4
-#define PCNET32_LOG_RX_BUFFERS 5
-#define PCNET32_LOG_MAX_TX_BUFFERS 9 /* 2^9 == 512 */
-#define PCNET32_LOG_MAX_RX_BUFFERS 9
+#define PCNET32_LOG_TX_BUFFERS 4
+#define PCNET32_LOG_RX_BUFFERS 5
#endif
#define TX_RING_SIZE (1 << (PCNET32_LOG_TX_BUFFERS))
-#define TX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_TX_BUFFERS))
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS ((PCNET32_LOG_TX_BUFFERS) << 12)
#define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS))
-#define RX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_RX_BUFFERS))
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS ((PCNET32_LOG_RX_BUFFERS) << 4)
#define PKT_BUF_SZ 1544
@@ -337,14 +334,14 @@ struct pcnet32_access {
};
/*
- * The first field of pcnet32_private is read by the ethernet device
- * so the structure should be allocated using pci_alloc_consistent().
+ * The first three fields of pcnet32_private are read by the ethernet device
+ * so we allocate the structure should be allocated by pci_alloc_consistent().
*/
struct pcnet32_private {
- struct pcnet32_init_block init_block;
/* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
- struct pcnet32_rx_head *rx_ring;
- struct pcnet32_tx_head *tx_ring;
+ struct pcnet32_rx_head rx_ring[RX_RING_SIZE];
+ struct pcnet32_tx_head tx_ring[TX_RING_SIZE];
+ struct pcnet32_init_block init_block;
dma_addr_t dma_addr; /* DMA address of beginning of this
object, returned by
pci_alloc_consistent */
@@ -352,21 +349,13 @@ struct pcnet32_private {
structure */
const char *name;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
- struct sk_buff **tx_skbuff;
- struct sk_buff **rx_skbuff;
- dma_addr_t *tx_dma_addr;
- dma_addr_t *rx_dma_addr;
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ dma_addr_t tx_dma_addr[TX_RING_SIZE];
+ dma_addr_t rx_dma_addr[RX_RING_SIZE];
struct pcnet32_access a;
spinlock_t lock; /* Guard lock */
unsigned int cur_rx, cur_tx; /* The next free ring entry */
- unsigned int rx_ring_size; /* current rx ring size */
- unsigned int tx_ring_size; /* current tx ring size */
- unsigned int rx_mod_mask; /* rx ring modular mask */
- unsigned int tx_mod_mask; /* tx ring modular mask */
- unsigned short rx_len_bits;
- unsigned short tx_len_bits;
- dma_addr_t rx_ring_dma_addr;
- dma_addr_t tx_ring_dma_addr;
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
struct net_device_stats stats;
char tx_full;
@@ -408,9 +397,6 @@ static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
static void pcnet32_purge_tx_ring(struct net_device *dev);
-static int pcnet32_alloc_ring(struct net_device *dev);
-static void pcnet32_free_ring(struct net_device *dev);
-
enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -627,62 +613,10 @@ static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringpar
{
struct pcnet32_private *lp = dev->priv;
- ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
- ering->tx_pending = lp->tx_ring_size - 1;
- ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
- ering->rx_pending = lp->rx_ring_size - 1;
-}
-
-static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
-{
- struct pcnet32_private *lp = dev->priv;
- unsigned long flags;
- int i;
-
- if (ering->rx_mini_pending || ering->rx_jumbo_pending)
- return -EINVAL;
-
- if (netif_running(dev))
- pcnet32_close(dev);
-
- spin_lock_irqsave(&lp->lock, flags);
- pcnet32_free_ring(dev);
- lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
- lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
-
- /* set the minimum ring size to 4, to allow the loopback test to work
- * unchanged.
- */
- for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
- if (lp->tx_ring_size <= (1 << i))
- break;
- }
- lp->tx_ring_size = (1 << i);
- lp->tx_mod_mask = lp->tx_ring_size - 1;
- lp->tx_len_bits = (i << 12);
-
- for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
- if (lp->rx_ring_size <= (1 << i))
- break;
- }
- lp->rx_ring_size = (1 << i);
- lp->rx_mod_mask = lp->rx_ring_size - 1;
- lp->rx_len_bits = (i << 4);
-
- if (pcnet32_alloc_ring(dev)) {
- pcnet32_free_ring(dev);
- return -ENOMEM;
- }
-
- spin_unlock_irqrestore(&lp->lock, flags);
-
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_INFO PFX "Ring Param Settings: RX: %d, TX: %d\n", lp->rx_ring_size, lp->tx_ring_size);
-
- if (netif_running(dev))
- pcnet32_open(dev);
-
- return 0;
+ ering->tx_max_pending = TX_RING_SIZE - 1;
+ ering->tx_pending = lp->cur_tx - lp->dirty_tx;
+ ering->rx_max_pending = RX_RING_SIZE - 1;
+ ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
}
static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -1014,7 +948,6 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.nway_reset = pcnet32_nway_reset,
.get_link = pcnet32_get_link,
.get_ringparam = pcnet32_get_ringparam,
- .set_ringparam = pcnet32_set_ringparam,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
.get_tso = ethtool_op_get_tso,
@@ -1024,7 +957,6 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.phys_id = pcnet32_phys_id,
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
/* only probes for non-PCI devices, the rest are handled by
@@ -1253,10 +1185,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
memcpy(dev->dev_addr, promaddr, 6);
}
}
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
- if (!is_valid_ether_addr(dev->perm_addr))
+ if (!is_valid_ether_addr(dev->dev_addr))
memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
if (pcnet32_debug & NETIF_MSG_PROBE) {
@@ -1308,12 +1239,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dev->priv = lp;
lp->name = chipname;
lp->shared_irq = shared;
- lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
- lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */
- lp->tx_mod_mask = lp->tx_ring_size - 1;
- lp->rx_mod_mask = lp->rx_ring_size - 1;
- lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
- lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
lp->mii_if.full_duplex = fdx;
lp->mii_if.phy_id_mask = 0x1f;
lp->mii_if.reg_num_mask = 0x1f;
@@ -1340,23 +1265,21 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
}
lp->a = *a;
- if (pcnet32_alloc_ring(dev)) {
- ret = -ENOMEM;
- goto err_free_ring;
- }
/* detect special T1/E1 WAN card by checking for MAC address */
if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
&& dev->dev_addr[2] == 0x75)
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
- lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
+ lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
lp->init_block.filter[0] = 0x00000000;
lp->init_block.filter[1] = 0x00000000;
- lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
- lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
+ lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
+ offsetof(struct pcnet32_private, rx_ring));
+ lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
+ offsetof(struct pcnet32_private, tx_ring));
/* switch pcnet32 to 32bit mode */
a->write_bcr(ioaddr, 20, 2);
@@ -1387,7 +1310,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", failed to detect IRQ line.\n");
ret = -ENODEV;
- goto err_free_ring;
+ goto err_free_consistent;
}
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", probed IRQ %d.\n", dev->irq);
@@ -1418,7 +1341,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
/* Fill in the generic fields of the device structure. */
if (register_netdev(dev))
- goto err_free_ring;
+ goto err_free_consistent;
if (pdev) {
pci_set_drvdata(pdev, dev);
@@ -1436,8 +1359,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
return 0;
-err_free_ring:
- pcnet32_free_ring(dev);
err_free_consistent:
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
err_free_netdev:
@@ -1448,86 +1369,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
}
-static int pcnet32_alloc_ring(struct net_device *dev)
-{
- struct pcnet32_private *lp = dev->priv;
-
- if ((lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
- &lp->tx_ring_dma_addr)) == NULL) {
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
- return -ENOMEM;
- }
-
- if ((lp->rx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
- &lp->rx_ring_dma_addr)) == NULL) {
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
- return -ENOMEM;
- }
-
- if (!(lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, GFP_ATOMIC))) {
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_ERR PFX "Memory allocation failed.\n");
- return -ENOMEM;
- }
- memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
-
- if (!(lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, GFP_ATOMIC))) {
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_ERR PFX "Memory allocation failed.\n");
- return -ENOMEM;
- }
- memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
-
- if (!(lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, GFP_ATOMIC))) {
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_ERR PFX "Memory allocation failed.\n");
- return -ENOMEM;
- }
- memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
-
- if (!(lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, GFP_ATOMIC))) {
- if (pcnet32_debug & NETIF_MSG_DRV)
- printk(KERN_ERR PFX "Memory allocation failed.\n");
- return -ENOMEM;
- }
- memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
-
- return 0;
-}
-
-
-static void pcnet32_free_ring(struct net_device *dev)
-{
- struct pcnet32_private *lp = dev->priv;
-
- kfree(lp->tx_skbuff);
- lp->tx_skbuff = NULL;
-
- kfree(lp->rx_skbuff);
- lp->rx_skbuff = NULL;
-
- kfree(lp->tx_dma_addr);
- lp->tx_dma_addr = NULL;
-
- kfree(lp->rx_dma_addr);
- lp->rx_dma_addr = NULL;
-
- if (lp->tx_ring) {
- pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
- lp->tx_ring, lp->tx_ring_dma_addr);
- lp->tx_ring = NULL;
- }
-
- if (lp->rx_ring) {
- pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
- lp->rx_ring, lp->rx_ring_dma_addr);
- lp->rx_ring = NULL;
- }
-}
-
-
static int
pcnet32_open(struct net_device *dev)
{
@@ -1559,8 +1400,8 @@ pcnet32_open(struct net_device *dev)
if (netif_msg_ifup(lp))
printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
dev->name, dev->irq,
- (u32) (lp->tx_ring_dma_addr),
- (u32) (lp->rx_ring_dma_addr),
+ (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
+ (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
(u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
/* set/reset autoselect bit */
@@ -1680,7 +1521,7 @@ pcnet32_open(struct net_device *dev)
err_free_ring:
/* free any allocated skbuffs */
- for (i = 0; i < lp->rx_ring_size; i++) {
+ for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_ring[i].status = 0;
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
@@ -1690,9 +1531,6 @@ pcnet32_open(struct net_device *dev)
lp->rx_skbuff[i] = NULL;
lp->rx_dma_addr[i] = 0;
}
-
- pcnet32_free_ring(dev);
-
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
@@ -1724,7 +1562,7 @@ pcnet32_purge_tx_ring(struct net_device *dev)
struct pcnet32_private *lp = dev->priv;
int i;
- for (i = 0; i < lp->tx_ring_size; i++) {
+ for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
@@ -1749,7 +1587,7 @@ pcnet32_init_ring(struct net_device *dev)
lp->cur_rx = lp->cur_tx = 0;
lp->dirty_rx = lp->dirty_tx = 0;
- for (i = 0; i < lp->rx_ring_size; i++) {
+ for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
if (rx_skbuff == NULL) {
if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
@@ -1773,18 +1611,20 @@ pcnet32_init_ring(struct net_device *dev)
}
/* The Tx buffer address is filled in as needed, but we do need to clear
* the upper ownership bit. */
- for (i = 0; i < lp->tx_ring_size; i++) {
+ for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
lp->tx_ring[i].base = 0;
lp->tx_dma_addr[i] = 0;
}
- lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
+ lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
- lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
- lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
+ lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
+ offsetof(struct pcnet32_private, rx_ring));
+ lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
+ offsetof(struct pcnet32_private, tx_ring));
wmb(); /* Make sure all changes are visible */
return 0;
}
@@ -1842,13 +1682,13 @@ pcnet32_tx_timeout (struct net_device *dev)
printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
lp->cur_rx);
- for (i = 0 ; i < lp->rx_ring_size; i++)
+ for (i = 0 ; i < RX_RING_SIZE; i++)
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
le32_to_cpu(lp->rx_ring[i].base),
(-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
le32_to_cpu(lp->rx_ring[i].msg_length),
le16_to_cpu(lp->rx_ring[i].status));
- for (i = 0 ; i < lp->tx_ring_size; i++)
+ for (i = 0 ; i < TX_RING_SIZE; i++)
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
le32_to_cpu(lp->tx_ring[i].base),
(-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
@@ -1889,7 +1729,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Fill in a Tx ring entry */
/* Mask to ring buffer boundary. */
- entry = lp->cur_tx & lp->tx_mod_mask;
+ entry = lp->cur_tx & TX_RING_MOD_MASK;
/* Caution: the write order is important here, set the status
* with the "ownership" bits last. */
@@ -1913,7 +1753,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) {
+ if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
lp->tx_full = 1;
netif_stop_queue(dev);
}
@@ -1966,7 +1806,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int delta;
while (dirty_tx != lp->cur_tx) {
- int entry = dirty_tx & lp->tx_mod_mask;
+ int entry = dirty_tx & TX_RING_MOD_MASK;
int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
if (status < 0)
@@ -2024,18 +1864,18 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dirty_tx++;
}
- delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
- if (delta > lp->tx_ring_size) {
+ delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
+ if (delta > TX_RING_SIZE) {
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
- dirty_tx += lp->tx_ring_size;
- delta -= lp->tx_ring_size;
+ dirty_tx += TX_RING_SIZE;
+ delta -= TX_RING_SIZE;
}
if (lp->tx_full &&
netif_queue_stopped(dev) &&
- delta < lp->tx_ring_size - 2) {
+ delta < TX_RING_SIZE - 2) {
/* The ring is no longer full, clear tbusy. */
lp->tx_full = 0;
netif_wake_queue (dev);
@@ -2092,8 +1932,8 @@ static int
pcnet32_rx(struct net_device *dev)
{
struct pcnet32_private *lp = dev->priv;
- int entry = lp->cur_rx & lp->rx_mod_mask;
- int boguscnt = lp->rx_ring_size / 2;
+ int entry = lp->cur_rx & RX_RING_MOD_MASK;
+ int boguscnt = RX_RING_SIZE / 2;
/* If we own the next entry, it's a new packet. Send it up. */
while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
@@ -2158,12 +1998,12 @@ pcnet32_rx(struct net_device *dev)
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
dev->name);
- for (i = 0; i < lp->rx_ring_size; i++)
+ for (i = 0; i < RX_RING_SIZE; i++)
if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
- & lp->rx_mod_mask].status) < 0)
+ & RX_RING_MOD_MASK].status) < 0)
break;
- if (i > lp->rx_ring_size -2) {
+ if (i > RX_RING_SIZE -2) {
lp->stats.rx_dropped++;
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
wmb(); /* Make sure adapter sees owner change */
@@ -2201,7 +2041,7 @@ pcnet32_rx(struct net_device *dev)
lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
wmb(); /* Make sure owner changes after all others are visible */
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
- entry = (++lp->cur_rx) & lp->rx_mod_mask;
+ entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
if (--boguscnt <= 0) break; /* don't stay in loop forever */
}
@@ -2244,7 +2084,7 @@ pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */
- for (i = 0; i < lp->rx_ring_size; i++) {
+ for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_ring[i].status = 0;
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
@@ -2256,7 +2096,7 @@ pcnet32_close(struct net_device *dev)
lp->rx_dma_addr[i] = 0;
}
- for (i = 0; i < lp->tx_ring_size; i++) {
+ for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
@@ -2425,7 +2265,6 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
struct pcnet32_private *lp = dev->priv;
unregister_netdev(dev);
- pcnet32_free_ring(dev);
release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
free_netdev(dev);
@@ -2501,7 +2340,6 @@ static void __exit pcnet32_cleanup_module(void)
struct pcnet32_private *lp = pcnet32_dev->priv;
next_dev = lp->next;
unregister_netdev(pcnet32_dev);
- pcnet32_free_ring(pcnet32_dev);
release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
free_netdev(pcnet32_dev);
diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig
index c782a6329805..14f4de1a8180 100644
--- a/trunk/drivers/net/phy/Kconfig
+++ b/trunk/drivers/net/phy/Kconfig
@@ -12,6 +12,14 @@ config PHYLIB
devices. This option provides infrastructure for
managing PHY devices.
+config PHYCONTROL
+ bool " Support for automatically handling PHY state changes"
+ depends on PHYLIB
+ help
+ Adds code to perform all the work for keeping PHY link
+ state (speed/duplex/etc) up-to-date. Also handles
+ interrupts.
+
comment "MII PHY device drivers"
depends on PHYLIB
diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c
index 9209da9dde0d..d9e11f93bf3a 100644
--- a/trunk/drivers/net/phy/phy.c
+++ b/trunk/drivers/net/phy/phy.c
@@ -242,6 +242,10 @@ EXPORT_SYMBOL(phy_sanitize_settings);
* choose the next best ones from the ones selected, so we don't
* care if ethtool tries to give us bad values
*
+ * A note about the PHYCONTROL Layer. If you turn off
+ * CONFIG_PHYCONTROL, you will need to read the PHY status
+ * registers after this function completes, and update your
+ * controller manually.
*/
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
{
@@ -376,6 +380,7 @@ int phy_start_aneg(struct phy_device *phydev)
err = phydev->drv->config_aneg(phydev);
+#ifdef CONFIG_PHYCONTROL
if (err < 0)
goto out_unlock;
@@ -390,12 +395,14 @@ int phy_start_aneg(struct phy_device *phydev)
}
out_unlock:
+#endif
spin_unlock(&phydev->lock);
return err;
}
EXPORT_SYMBOL(phy_start_aneg);
+#ifdef CONFIG_PHYCONTROL
static void phy_change(void *data);
static void phy_timer(unsigned long data);
@@ -861,3 +868,4 @@ static void phy_timer(unsigned long data)
mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
}
+#endif /* CONFIG_PHYCONTROL */
diff --git a/trunk/drivers/net/phy/phy_device.c b/trunk/drivers/net/phy/phy_device.c
index 6da1aa0706a1..33f7bdb5857c 100644
--- a/trunk/drivers/net/phy/phy_device.c
+++ b/trunk/drivers/net/phy/phy_device.c
@@ -101,6 +101,7 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
return dev;
}
+#ifdef CONFIG_PHYCONTROL
/* phy_prepare_link:
*
* description: Tells the PHY infrastructure to handle the
@@ -159,6 +160,8 @@ void phy_disconnect(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_disconnect);
+#endif /* CONFIG_PHYCONTROL */
+
/* phy_attach:
*
* description: Called by drivers to attach to a particular PHY
diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c
index 159b56a56ef4..afb3f186b884 100644
--- a/trunk/drivers/net/r8169.c
+++ b/trunk/drivers/net/r8169.c
@@ -1027,7 +1027,6 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_strings = rtl8169_get_strings,
.get_stats_count = rtl8169_get_stats_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1512,7 +1511,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Get MAC address. FIXME: read EEPROM */
for (i = 0; i < MAC_ADDR_LEN; i++)
dev->dev_addr[i] = RTL_R8(MAC0 + i);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->open = rtl8169_open;
dev->hard_start_xmit = rtl8169_start_xmit;
diff --git a/trunk/drivers/net/rionet.c b/trunk/drivers/net/rionet.c
deleted file mode 100644
index 12cde0604580..000000000000
--- a/trunk/drivers/net/rionet.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * rionet - Ethernet driver over RapidIO messaging 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
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#define DRV_NAME "rionet"
-#define DRV_VERSION "0.2"
-#define DRV_AUTHOR "Matt Porter "
-#define DRV_DESC "Ethernet over RapidIO"
-
-MODULE_AUTHOR(DRV_AUTHOR);
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_LICENSE("GPL");
-
-#define RIONET_DEFAULT_MSGLEVEL \
- (NETIF_MSG_DRV | \
- NETIF_MSG_LINK | \
- NETIF_MSG_RX_ERR | \
- NETIF_MSG_TX_ERR)
-
-#define RIONET_DOORBELL_JOIN 0x1000
-#define RIONET_DOORBELL_LEAVE 0x1001
-
-#define RIONET_MAILBOX 0
-
-#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
-#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
-
-static LIST_HEAD(rionet_peers);
-
-struct rionet_private {
- struct rio_mport *mport;
- struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
- struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
- struct net_device_stats stats;
- int rx_slot;
- int tx_slot;
- int tx_cnt;
- int ack_slot;
- spinlock_t lock;
- spinlock_t tx_lock;
- u32 msg_enable;
-};
-
-struct rionet_peer {
- struct list_head node;
- struct rio_dev *rdev;
- struct resource *res;
-};
-
-static int rionet_check = 0;
-static int rionet_capable = 1;
-
-/*
- * This is a fast lookup table for for translating TX
- * Ethernet packets into a destination RIO device. It
- * could be made into a hash table to save memory depending
- * on system trade-offs.
- */
-static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
-
-#define is_rionet_capable(pef, src_ops, dst_ops) \
- ((pef & RIO_PEF_INB_MBOX) && \
- (pef & RIO_PEF_INB_DOORBELL) && \
- (src_ops & RIO_SRC_OPS_DOORBELL) && \
- (dst_ops & RIO_DST_OPS_DOORBELL))
-#define dev_rionet_capable(dev) \
- is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
-
-#define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001)
-#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4))
-
-static struct net_device_stats *rionet_stats(struct net_device *ndev)
-{
- struct rionet_private *rnet = ndev->priv;
- return &rnet->stats;
-}
-
-static int rionet_rx_clean(struct net_device *ndev)
-{
- int i;
- int error = 0;
- struct rionet_private *rnet = ndev->priv;
- void *data;
-
- i = rnet->rx_slot;
-
- do {
- if (!rnet->rx_skb[i])
- continue;
-
- if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
- break;
-
- rnet->rx_skb[i]->data = data;
- skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
- rnet->rx_skb[i]->dev = ndev;
- rnet->rx_skb[i]->protocol =
- eth_type_trans(rnet->rx_skb[i], ndev);
- error = netif_rx(rnet->rx_skb[i]);
-
- if (error == NET_RX_DROP) {
- rnet->stats.rx_dropped++;
- } else if (error == NET_RX_BAD) {
- if (netif_msg_rx_err(rnet))
- printk(KERN_WARNING "%s: bad rx packet\n",
- DRV_NAME);
- rnet->stats.rx_errors++;
- } else {
- rnet->stats.rx_packets++;
- rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
- }
-
- } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
-
- return i;
-}
-
-static void rionet_rx_fill(struct net_device *ndev, int end)
-{
- int i;
- struct rionet_private *rnet = ndev->priv;
-
- i = rnet->rx_slot;
- do {
- rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
-
- if (!rnet->rx_skb[i])
- break;
-
- rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
- rnet->rx_skb[i]->data);
- } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
-
- rnet->rx_slot = i;
-}
-
-static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
- struct rio_dev *rdev)
-{
- struct rionet_private *rnet = ndev->priv;
-
- rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
- rnet->tx_skb[rnet->tx_slot] = skb;
-
- rnet->stats.tx_packets++;
- rnet->stats.tx_bytes += skb->len;
-
- if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
- netif_stop_queue(ndev);
-
- ++rnet->tx_slot;
- rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
-
- if (netif_msg_tx_queued(rnet))
- printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
- (u32) skb, skb->len);
-
- return 0;
-}
-
-static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
- int i;
- struct rionet_private *rnet = ndev->priv;
- struct ethhdr *eth = (struct ethhdr *)skb->data;
- u16 destid;
- unsigned long flags;
-
- local_irq_save(flags);
- if (!spin_trylock(&rnet->tx_lock)) {
- local_irq_restore(flags);
- return NETDEV_TX_LOCKED;
- }
-
- if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
- netif_stop_queue(ndev);
- spin_unlock_irqrestore(&rnet->tx_lock, flags);
- printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
- ndev->name);
- return NETDEV_TX_BUSY;
- }
-
- if (eth->h_dest[0] & 0x01) {
- for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
- if (rionet_active[i])
- rionet_queue_tx_msg(skb, ndev,
- rionet_active[i]);
- } else if (RIONET_MAC_MATCH(eth->h_dest)) {
- destid = RIONET_GET_DESTID(eth->h_dest);
- if (rionet_active[destid])
- rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
- }
-
- spin_unlock_irqrestore(&rnet->tx_lock, flags);
-
- return 0;
-}
-
-static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
- u16 info)
-{
- struct net_device *ndev = dev_id;
- struct rionet_private *rnet = ndev->priv;
- struct rionet_peer *peer;
-
- if (netif_msg_intr(rnet))
- printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
- DRV_NAME, sid, tid, info);
- if (info == RIONET_DOORBELL_JOIN) {
- if (!rionet_active[sid]) {
- list_for_each_entry(peer, &rionet_peers, node) {
- if (peer->rdev->destid == sid)
- rionet_active[sid] = peer->rdev;
- }
- rio_mport_send_doorbell(mport, sid,
- RIONET_DOORBELL_JOIN);
- }
- } else if (info == RIONET_DOORBELL_LEAVE) {
- rionet_active[sid] = NULL;
- } else {
- if (netif_msg_intr(rnet))
- printk(KERN_WARNING "%s: unhandled doorbell\n",
- DRV_NAME);
- }
-}
-
-static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
-{
- int n;
- struct net_device *ndev = dev_id;
- struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
-
- if (netif_msg_intr(rnet))
- printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
- DRV_NAME, mbox, slot);
-
- spin_lock(&rnet->lock);
- if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
- rionet_rx_fill(ndev, n);
- spin_unlock(&rnet->lock);
-}
-
-static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
-{
- struct net_device *ndev = dev_id;
- struct rionet_private *rnet = ndev->priv;
-
- spin_lock(&rnet->lock);
-
- if (netif_msg_intr(rnet))
- printk(KERN_INFO
- "%s: outbound message event, mbox %d slot %d\n",
- DRV_NAME, mbox, slot);
-
- while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
- /* dma unmap single */
- dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
- rnet->tx_skb[rnet->ack_slot] = NULL;
- ++rnet->ack_slot;
- rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
- rnet->tx_cnt--;
- }
-
- if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
- netif_wake_queue(ndev);
-
- spin_unlock(&rnet->lock);
-}
-
-static int rionet_open(struct net_device *ndev)
-{
- int i, rc = 0;
- struct rionet_peer *peer, *tmp;
- u32 pwdcsr;
- struct rionet_private *rnet = ndev->priv;
-
- if (netif_msg_ifup(rnet))
- printk(KERN_INFO "%s: open\n", DRV_NAME);
-
- if ((rc = rio_request_inb_dbell(rnet->mport,
- (void *)ndev,
- RIONET_DOORBELL_JOIN,
- RIONET_DOORBELL_LEAVE,
- rionet_dbell_event)) < 0)
- goto out;
-
- if ((rc = rio_request_inb_mbox(rnet->mport,
- (void *)ndev,
- RIONET_MAILBOX,
- RIONET_RX_RING_SIZE,
- rionet_inb_msg_event)) < 0)
- goto out;
-
- if ((rc = rio_request_outb_mbox(rnet->mport,
- (void *)ndev,
- RIONET_MAILBOX,
- RIONET_TX_RING_SIZE,
- rionet_outb_msg_event)) < 0)
- goto out;
-
- /* Initialize inbound message ring */
- for (i = 0; i < RIONET_RX_RING_SIZE; i++)
- rnet->rx_skb[i] = NULL;
- rnet->rx_slot = 0;
- rionet_rx_fill(ndev, 0);
-
- rnet->tx_slot = 0;
- rnet->tx_cnt = 0;
- rnet->ack_slot = 0;
-
- netif_carrier_on(ndev);
- netif_start_queue(ndev);
-
- list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
- if (!(peer->res = rio_request_outb_dbell(peer->rdev,
- RIONET_DOORBELL_JOIN,
- RIONET_DOORBELL_LEAVE)))
- {
- printk(KERN_ERR "%s: error requesting doorbells\n",
- DRV_NAME);
- continue;
- }
-
- /*
- * If device has initialized inbound doorbells,
- * send a join message
- */
- rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
- if (pwdcsr & RIO_DOORBELL_AVAIL)
- rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
- }
-
- out:
- return rc;
-}
-
-static int rionet_close(struct net_device *ndev)
-{
- struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
- struct rionet_peer *peer, *tmp;
- int i;
-
- if (netif_msg_ifup(rnet))
- printk(KERN_INFO "%s: close\n", DRV_NAME);
-
- netif_stop_queue(ndev);
- netif_carrier_off(ndev);
-
- for (i = 0; i < RIONET_RX_RING_SIZE; i++)
- if (rnet->rx_skb[i])
- kfree_skb(rnet->rx_skb[i]);
-
- list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
- if (rionet_active[peer->rdev->destid]) {
- rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
- rionet_active[peer->rdev->destid] = NULL;
- }
- rio_release_outb_dbell(peer->rdev, peer->res);
- }
-
- rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
- RIONET_DOORBELL_LEAVE);
- rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
- rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
-
- return 0;
-}
-
-static void rionet_remove(struct rio_dev *rdev)
-{
- struct net_device *ndev = NULL;
- struct rionet_peer *peer, *tmp;
-
- unregister_netdev(ndev);
- kfree(ndev);
-
- list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
- list_del(&peer->node);
- kfree(peer);
- }
-}
-
-static void rionet_get_drvinfo(struct net_device *ndev,
- struct ethtool_drvinfo *info)
-{
- struct rionet_private *rnet = ndev->priv;
-
- strcpy(info->driver, DRV_NAME);
- strcpy(info->version, DRV_VERSION);
- strcpy(info->fw_version, "n/a");
- strcpy(info->bus_info, rnet->mport->name);
-}
-
-static u32 rionet_get_msglevel(struct net_device *ndev)
-{
- struct rionet_private *rnet = ndev->priv;
-
- return rnet->msg_enable;
-}
-
-static void rionet_set_msglevel(struct net_device *ndev, u32 value)
-{
- struct rionet_private *rnet = ndev->priv;
-
- rnet->msg_enable = value;
-}
-
-static struct ethtool_ops rionet_ethtool_ops = {
- .get_drvinfo = rionet_get_drvinfo,
- .get_msglevel = rionet_get_msglevel,
- .set_msglevel = rionet_set_msglevel,
- .get_link = ethtool_op_get_link,
-};
-
-static int rionet_setup_netdev(struct rio_mport *mport)
-{
- int rc = 0;
- struct net_device *ndev = NULL;
- struct rionet_private *rnet;
- u16 device_id;
-
- /* Allocate our net_device structure */
- ndev = alloc_etherdev(sizeof(struct rionet_private));
- if (ndev == NULL) {
- printk(KERN_INFO "%s: could not allocate ethernet device.\n",
- DRV_NAME);
- rc = -ENOMEM;
- goto out;
- }
-
- /* Set up private area */
- rnet = (struct rionet_private *)ndev->priv;
- rnet->mport = mport;
-
- /* Set the default MAC address */
- device_id = rio_local_get_device_id(mport);
- ndev->dev_addr[0] = 0x00;
- ndev->dev_addr[1] = 0x01;
- ndev->dev_addr[2] = 0x00;
- ndev->dev_addr[3] = 0x01;
- ndev->dev_addr[4] = device_id >> 8;
- ndev->dev_addr[5] = device_id & 0xff;
-
- /* Fill in the driver function table */
- ndev->open = &rionet_open;
- ndev->hard_start_xmit = &rionet_start_xmit;
- ndev->stop = &rionet_close;
- ndev->get_stats = &rionet_stats;
- ndev->mtu = RIO_MAX_MSG_SIZE - 14;
- ndev->features = NETIF_F_LLTX;
- SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
-
- SET_MODULE_OWNER(ndev);
-
- spin_lock_init(&rnet->lock);
- spin_lock_init(&rnet->tx_lock);
-
- rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
-
- rc = register_netdev(ndev);
- if (rc != 0)
- goto out;
-
- printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->name,
- DRV_NAME,
- DRV_DESC,
- DRV_VERSION,
- ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
- ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
-
- out:
- return rc;
-}
-
-/*
- * XXX Make multi-net safe
- */
-static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
-{
- int rc = -ENODEV;
- u32 lpef, lsrc_ops, ldst_ops;
- struct rionet_peer *peer;
-
- /* If local device is not rionet capable, give up quickly */
- if (!rionet_capable)
- goto out;
-
- /*
- * First time through, make sure local device is rionet
- * capable, setup netdev, and set flags so this is skipped
- * on later probes
- */
- if (!rionet_check) {
- rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
- rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
- &lsrc_ops);
- rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
- &ldst_ops);
- if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
- printk(KERN_ERR
- "%s: local device is not network capable\n",
- DRV_NAME);
- rionet_check = 1;
- rionet_capable = 0;
- goto out;
- }
-
- rc = rionet_setup_netdev(rdev->net->hport);
- rionet_check = 1;
- }
-
- /*
- * If the remote device has mailbox/doorbell capabilities,
- * add it to the peer list.
- */
- if (dev_rionet_capable(rdev)) {
- if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
- rc = -ENOMEM;
- goto out;
- }
- peer->rdev = rdev;
- list_add_tail(&peer->node, &rionet_peers);
- }
-
- out:
- return rc;
-}
-
-static struct rio_device_id rionet_id_table[] = {
- {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
-};
-
-static struct rio_driver rionet_driver = {
- .name = "rionet",
- .id_table = rionet_id_table,
- .probe = rionet_probe,
- .remove = rionet_remove,
-};
-
-static int __init rionet_init(void)
-{
- return rio_register_driver(&rionet_driver);
-}
-
-static void __exit rionet_exit(void)
-{
- rio_unregister_driver(&rionet_driver);
-}
-
-module_init(rionet_init);
-module_exit(rionet_exit);
diff --git a/trunk/drivers/net/s2io-regs.h b/trunk/drivers/net/s2io-regs.h
index 00179bc3437f..7cefe5507b9e 100644
--- a/trunk/drivers/net/s2io-regs.h
+++ b/trunk/drivers/net/s2io-regs.h
@@ -814,17 +814,6 @@ typedef struct _XENA_dev_config {
u64 rxgxs_ber_0; /* CHANGED */
u64 rxgxs_ber_1; /* CHANGED */
- u64 spi_control;
-#define SPI_CONTROL_KEY(key) vBIT(key,0,4)
-#define SPI_CONTROL_BYTECNT(cnt) vBIT(cnt,29,3)
-#define SPI_CONTROL_CMD(cmd) vBIT(cmd,32,8)
-#define SPI_CONTROL_ADDR(addr) vBIT(addr,40,24)
-#define SPI_CONTROL_SEL1 BIT(4)
-#define SPI_CONTROL_REQ BIT(7)
-#define SPI_CONTROL_NACK BIT(5)
-#define SPI_CONTROL_DONE BIT(6)
- u64 spi_data;
-#define SPI_DATA_WRITE(data,len) vBIT(data,0,len)
} XENA_dev_config_t;
#define XENA_REG_SPACE sizeof(XENA_dev_config_t)
diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c
index d303d162974f..dd451e099a4c 100644
--- a/trunk/drivers/net/s2io.c
+++ b/trunk/drivers/net/s2io.c
@@ -65,11 +65,9 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "Version 2.0.9.1"
-
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = DRV_VERSION;
+static char s2io_driver_version[] = "Version 2.0.8.1";
static inline int RXD_IS_UP2DT(RxD_t *rxdp)
{
@@ -309,8 +307,6 @@ static unsigned int indicate_max_pkts;
#endif
/* Frequency of Rx desc syncs expressed as power of 2 */
static unsigned int rxsync_frequency = 3;
-/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
-static unsigned int intr_type = 0;
/*
* S2IO device table.
@@ -1400,13 +1396,8 @@ static int init_nic(struct s2io_nic *nic)
writeq(val64, &bar0->rti_data1_mem);
val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
- RTI_DATA2_MEM_RX_UFC_B(0x2) ;
- if (nic->intr_type == MSI_X)
- val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
- RTI_DATA2_MEM_RX_UFC_D(0x40));
- else
- val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
- RTI_DATA2_MEM_RX_UFC_D(0x80));
+ RTI_DATA2_MEM_RX_UFC_B(0x2) |
+ RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
writeq(val64, &bar0->rti_data2_mem);
for (i = 0; i < config->rx_ring_num; i++) {
@@ -1516,15 +1507,17 @@ static int init_nic(struct s2io_nic *nic)
#define LINK_UP_DOWN_INTERRUPT 1
#define MAC_RMAC_ERR_TIMER 2
+#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
+#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
+#else
int s2io_link_fault_indication(nic_t *nic)
{
- if (nic->intr_type != INTA)
- return MAC_RMAC_ERR_TIMER;
if (nic->device_type == XFRAME_II_DEVICE)
return LINK_UP_DOWN_INTERRUPT;
else
return MAC_RMAC_ERR_TIMER;
}
+#endif
/**
* en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1948,14 +1941,11 @@ static int start_nic(struct s2io_nic *nic)
}
/* Enable select interrupts */
- if (nic->intr_type != INTA)
- en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
- else {
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
- interruptible |= TX_PIC_INTR | RX_PIC_INTR;
- interruptible |= TX_MAC_INTR | RX_MAC_INTR;
- en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
- }
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+
+ en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
/*
* With some switches, link might be already up at this point.
@@ -2643,11 +2633,11 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
err = txdlp->Control_1 & TXD_T_CODE;
if ((err >> 48) == 0xA) {
DBG_PRINT(TX_DBG, "TxD returned due \
-to loss of link\n");
+ to loss of link\n");
}
else {
DBG_PRINT(ERR_DBG, "***TxD error \
-%llx\n", err);
+ %llx\n", err);
}
}
@@ -2864,9 +2854,6 @@ void s2io_reset(nic_t * sp)
/* Set swapper to enable I/O register access */
s2io_set_swapper(sp);
- /* Restore the MSIX table entries from local variables */
- restore_xmsi_data(sp);
-
/* Clear certain PCI/PCI-X fields after reset */
if (sp->device_type == XFRAME_II_DEVICE) {
/* Clear parity err detect bit */
@@ -2996,9 +2983,8 @@ int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_RXD_W_FE |
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
+ SWAPPER_CTRL_XMSI_SE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- if (sp->intr_type == INTA)
- val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#else
/*
@@ -3019,9 +3005,8 @@ int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_RXD_W_SE |
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
+ SWAPPER_CTRL_XMSI_SE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- if (sp->intr_type == INTA)
- val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#endif
val64 = readq(&bar0->swapper_ctrl);
@@ -3043,201 +3028,6 @@ int s2io_set_swapper(nic_t * sp)
return SUCCESS;
}
-int wait_for_msix_trans(nic_t *nic, int i)
-{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
- u64 val64;
- int ret = 0, cnt = 0;
-
- do {
- val64 = readq(&bar0->xmsi_access);
- if (!(val64 & BIT(15)))
- break;
- mdelay(1);
- cnt++;
- } while(cnt < 5);
- if (cnt == 5) {
- DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
- ret = 1;
- }
-
- return ret;
-}
-
-void restore_xmsi_data(nic_t *nic)
-{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
- u64 val64;
- int i;
-
- for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
- writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
- writeq(nic->msix_info[i].data, &bar0->xmsi_data);
- val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
- writeq(val64, &bar0->xmsi_access);
- if (wait_for_msix_trans(nic, i)) {
- DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
- continue;
- }
- }
-}
-
-void store_xmsi_data(nic_t *nic)
-{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
- u64 val64, addr, data;
- int i;
-
- /* Store and display */
- for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
- val64 = (BIT(15) | vBIT(i, 26, 6));
- writeq(val64, &bar0->xmsi_access);
- if (wait_for_msix_trans(nic, i)) {
- DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
- continue;
- }
- addr = readq(&bar0->xmsi_address);
- data = readq(&bar0->xmsi_data);
- if (addr && data) {
- nic->msix_info[i].addr = addr;
- nic->msix_info[i].data = data;
- }
- }
-}
-
-int s2io_enable_msi(nic_t *nic)
-{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
- u16 msi_ctrl, msg_val;
- struct config_param *config = &nic->config;
- struct net_device *dev = nic->dev;
- u64 val64, tx_mat, rx_mat;
- int i, err;
-
- val64 = readq(&bar0->pic_control);
- val64 &= ~BIT(1);
- writeq(val64, &bar0->pic_control);
-
- err = pci_enable_msi(nic->pdev);
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
- nic->dev->name);
- return err;
- }
-
- /*
- * Enable MSI and use MSI-1 in stead of the standard MSI-0
- * for interrupt handling.
- */
- pci_read_config_word(nic->pdev, 0x4c, &msg_val);
- msg_val ^= 0x1;
- pci_write_config_word(nic->pdev, 0x4c, msg_val);
- pci_read_config_word(nic->pdev, 0x4c, &msg_val);
-
- pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
- msi_ctrl |= 0x10;
- pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
-
- /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
- tx_mat = readq(&bar0->tx_mat0_n[0]);
- for (i=0; itx_fifo_num; i++) {
- tx_mat |= TX_MAT_SET(i, 1);
- }
- writeq(tx_mat, &bar0->tx_mat0_n[0]);
-
- rx_mat = readq(&bar0->rx_mat);
- for (i=0; irx_ring_num; i++) {
- rx_mat |= RX_MAT_SET(i, 1);
- }
- writeq(rx_mat, &bar0->rx_mat);
-
- dev->irq = nic->pdev->irq;
- return 0;
-}
-
-int s2io_enable_msi_x(nic_t *nic)
-{
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
- u64 tx_mat, rx_mat;
- u16 msi_control; /* Temp variable */
- int ret, i, j, msix_indx = 1;
-
- nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
- GFP_KERNEL);
- if (nic->entries == NULL) {
- DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
- return -ENOMEM;
- }
- memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
-
- nic->s2io_entries =
- kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
- GFP_KERNEL);
- if (nic->s2io_entries == NULL) {
- DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
- kfree(nic->entries);
- return -ENOMEM;
- }
- memset(nic->s2io_entries, 0,
- MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
-
- for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
- nic->entries[i].entry = i;
- nic->s2io_entries[i].entry = i;
- nic->s2io_entries[i].arg = NULL;
- nic->s2io_entries[i].in_use = 0;
- }
-
- tx_mat = readq(&bar0->tx_mat0_n[0]);
- for (i=0; iconfig.tx_fifo_num; i++, msix_indx++) {
- tx_mat |= TX_MAT_SET(i, msix_indx);
- nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
- nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
- nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
- }
- writeq(tx_mat, &bar0->tx_mat0_n[0]);
-
- if (!nic->config.bimodal) {
- rx_mat = readq(&bar0->rx_mat);
- for (j=0; jconfig.rx_ring_num; j++, msix_indx++) {
- rx_mat |= RX_MAT_SET(j, msix_indx);
- nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
- nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
- nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
- }
- writeq(rx_mat, &bar0->rx_mat);
- } else {
- tx_mat = readq(&bar0->tx_mat0_n[7]);
- for (j=0; jconfig.rx_ring_num; j++, msix_indx++) {
- tx_mat |= TX_MAT_SET(i, msix_indx);
- nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
- nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
- nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
- }
- writeq(tx_mat, &bar0->tx_mat0_n[7]);
- }
-
- ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
- if (ret) {
- DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
- kfree(nic->entries);
- kfree(nic->s2io_entries);
- nic->entries = NULL;
- nic->s2io_entries = NULL;
- return -ENOMEM;
- }
-
- /*
- * To enable MSI-X, MSI also needs to be enabled, due to a bug
- * in the herc NIC. (Temp change, needs to be removed later)
- */
- pci_read_config_word(nic->pdev, 0x42, &msi_control);
- msi_control |= 0x1; /* Enable MSI */
- pci_write_config_word(nic->pdev, 0x42, msi_control);
-
- return 0;
-}
-
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
@@ -3258,8 +3048,6 @@ int s2io_open(struct net_device *dev)
{
nic_t *sp = dev->priv;
int err = 0;
- int i;
- u16 msi_control; /* Temp variable */
/*
* Make sure you have link off by default every time
@@ -3276,55 +3064,13 @@ int s2io_open(struct net_device *dev)
goto hw_init_failed;
}
- /* Store the values of the MSIX table in the nic_t structure */
- store_xmsi_data(sp);
-
/* After proper initialization of H/W, register ISR */
- if (sp->intr_type == MSI) {
- err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
- SA_SHIRQ, sp->name, dev);
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: MSI registration \
-failed\n", dev->name);
- goto isr_registration_failed;
- }
- }
- if (sp->intr_type == MSI_X) {
- for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
- if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
- sprintf(sp->desc1, "%s:MSI-X-%d-TX",
- dev->name, i);
- err = request_irq(sp->entries[i].vector,
- s2io_msix_fifo_handle, 0, sp->desc1,
- sp->s2io_entries[i].arg);
- DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
- sp->msix_info[i].addr);
- } else {
- sprintf(sp->desc2, "%s:MSI-X-%d-RX",
- dev->name, i);
- err = request_irq(sp->entries[i].vector,
- s2io_msix_ring_handle, 0, sp->desc2,
- sp->s2io_entries[i].arg);
- DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
- sp->msix_info[i].addr);
- }
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
-failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
- goto isr_registration_failed;
- }
- sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
- }
- }
- if (sp->intr_type == INTA) {
- err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
- sp->name, dev);
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
- dev->name);
- goto isr_registration_failed;
- }
+ err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+ sp->name, dev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+ dev->name);
+ goto isr_registration_failed;
}
if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
@@ -3337,37 +3083,11 @@ failed\n", dev->name, i);
return 0;
setting_mac_address_failed:
- if (sp->intr_type != MSI_X)
- free_irq(sp->pdev->irq, dev);
+ free_irq(sp->pdev->irq, dev);
isr_registration_failed:
del_timer_sync(&sp->alarm_timer);
- if (sp->intr_type == MSI_X) {
- if (sp->device_type == XFRAME_II_DEVICE) {
- for (i=1; (sp->s2io_entries[i].in_use ==
- MSIX_REGISTERED_SUCCESS); i++) {
- int vector = sp->entries[i].vector;
- void *arg = sp->s2io_entries[i].arg;
-
- free_irq(vector, arg);
- }
- pci_disable_msix(sp->pdev);
-
- /* Temp */
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
- }
- }
- else if (sp->intr_type == MSI)
- pci_disable_msi(sp->pdev);
s2io_reset(sp);
hw_init_failed:
- if (sp->intr_type == MSI_X) {
- if (sp->entries)
- kfree(sp->entries);
- if (sp->s2io_entries)
- kfree(sp->s2io_entries);
- }
return err;
}
@@ -3387,35 +3107,12 @@ failed\n", dev->name, i);
int s2io_close(struct net_device *dev)
{
nic_t *sp = dev->priv;
- int i;
- u16 msi_control;
-
flush_scheduled_work();
netif_stop_queue(dev);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- if (sp->intr_type == MSI_X) {
- if (sp->device_type == XFRAME_II_DEVICE) {
- for (i=1; (sp->s2io_entries[i].in_use ==
- MSIX_REGISTERED_SUCCESS); i++) {
- int vector = sp->entries[i].vector;
- void *arg = sp->s2io_entries[i].arg;
-
- free_irq(vector, arg);
- }
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
- }
- }
- else {
- free_irq(sp->pdev->irq, dev);
- if (sp->intr_type == MSI)
- pci_disable_msi(sp->pdev);
- }
+ free_irq(sp->pdev->irq, dev);
sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -3581,104 +3278,6 @@ s2io_alarm_handle(unsigned long data)
mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
}
-static irqreturn_t
-s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- nic_t *sp = dev->priv;
- int i;
- int ret;
- mac_info_t *mac_control;
- struct config_param *config;
-
- atomic_inc(&sp->isr_cnt);
- mac_control = &sp->mac_control;
- config = &sp->config;
- DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
-
- /* If Intr is because of Rx Traffic */
- for (i = 0; i < config->rx_ring_num; i++)
- rx_intr_handler(&mac_control->rings[i]);
-
- /* If Intr is because of Tx Traffic */
- for (i = 0; i < config->tx_fifo_num; i++)
- tx_intr_handler(&mac_control->fifos[i]);
-
- /*
- * If the Rx buffer count is below the panic threshold then
- * reallocate the buffers from the interrupt handler itself,
- * else schedule a tasklet to reallocate the buffers.
- */
- for (i = 0; i < config->rx_ring_num; i++) {
- int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
- int level = rx_buffer_level(sp, rxb_size, i);
-
- if ((level == PANIC) && (!TASKLET_IN_USE)) {
- DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
- DBG_PRINT(INTR_DBG, "PANIC levels\n");
- if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
- DBG_PRINT(ERR_DBG, "%s:Out of memory",
- dev->name);
- DBG_PRINT(ERR_DBG, " in ISR!!\n");
- clear_bit(0, (&sp->tasklet_status));
- atomic_dec(&sp->isr_cnt);
- return IRQ_HANDLED;
- }
- clear_bit(0, (&sp->tasklet_status));
- } else if (level == LOW) {
- tasklet_schedule(&sp->task);
- }
- }
-
- atomic_dec(&sp->isr_cnt);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t
-s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
- ring_info_t *ring = (ring_info_t *)dev_id;
- nic_t *sp = ring->nic;
- int rxb_size, level, rng_n;
-
- atomic_inc(&sp->isr_cnt);
- rx_intr_handler(ring);
-
- rng_n = ring->ring_no;
- rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
- level = rx_buffer_level(sp, rxb_size, rng_n);
-
- if ((level == PANIC) && (!TASKLET_IN_USE)) {
- int ret;
- DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
- DBG_PRINT(INTR_DBG, "PANIC levels\n");
- if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
- DBG_PRINT(ERR_DBG, "Out of memory in %s",
- __FUNCTION__);
- clear_bit(0, (&sp->tasklet_status));
- return IRQ_HANDLED;
- }
- clear_bit(0, (&sp->tasklet_status));
- } else if (level == LOW) {
- tasklet_schedule(&sp->task);
- }
- atomic_dec(&sp->isr_cnt);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t
-s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
- fifo_info_t *fifo = (fifo_info_t *)dev_id;
- nic_t *sp = fifo->nic;
-
- atomic_inc(&sp->isr_cnt);
- tx_intr_handler(fifo);
- atomic_dec(&sp->isr_cnt);
- return IRQ_HANDLED;
-}
-
static void s2io_txpic_intr_handle(nic_t *sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -4179,10 +3778,11 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
{
nic_t *sp = dev->priv;
- strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
- strncpy(info->version, s2io_driver_version, sizeof(info->version));
- strncpy(info->fw_version, "", sizeof(info->fw_version));
- strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
+ strncpy(info->driver, s2io_driver_name, sizeof(s2io_driver_name));
+ strncpy(info->version, s2io_driver_version,
+ sizeof(s2io_driver_version));
+ strncpy(info->fw_version, "", 32);
+ strncpy(info->bus_info, pci_name(sp->pdev), 32);
info->regdump_len = XENA_REG_SPACE;
info->eedump_len = XENA_EEPROM_SPACE;
info->testinfo_len = S2IO_TEST_LEN;
@@ -4378,53 +3978,29 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
*/
#define S2IO_DEV_ID 5
-static int read_eeprom(nic_t * sp, int off, u64 * data)
+static int read_eeprom(nic_t * sp, int off, u32 * data)
{
int ret = -1;
u32 exit_cnt = 0;
u64 val64;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- if (sp->device_type == XFRAME_I_DEVICE) {
- val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
- I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
- I2C_CONTROL_CNTL_START;
- SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+ val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+ I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
+ I2C_CONTROL_CNTL_START;
+ SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
- while (exit_cnt < 5) {
- val64 = readq(&bar0->i2c_control);
- if (I2C_CONTROL_CNTL_END(val64)) {
- *data = I2C_CONTROL_GET_DATA(val64);
- ret = 0;
- break;
- }
- msleep(50);
- exit_cnt++;
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->i2c_control);
+ if (I2C_CONTROL_CNTL_END(val64)) {
+ *data = I2C_CONTROL_GET_DATA(val64);
+ ret = 0;
+ break;
}
+ msleep(50);
+ exit_cnt++;
}
- if (sp->device_type == XFRAME_II_DEVICE) {
- val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
- SPI_CONTROL_BYTECNT(0x3) |
- SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
- SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
- val64 |= SPI_CONTROL_REQ;
- SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
- while (exit_cnt < 5) {
- val64 = readq(&bar0->spi_control);
- if (val64 & SPI_CONTROL_NACK) {
- ret = 1;
- break;
- } else if (val64 & SPI_CONTROL_DONE) {
- *data = readq(&bar0->spi_data);
- *data &= 0xffffff;
- ret = 0;
- break;
- }
- msleep(50);
- exit_cnt++;
- }
- }
return ret;
}
@@ -4443,53 +4019,28 @@ static int read_eeprom(nic_t * sp, int off, u64 * data)
* 0 on success, -1 on failure.
*/
-static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
+static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
{
int exit_cnt = 0, ret = -1;
u64 val64;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- if (sp->device_type == XFRAME_I_DEVICE) {
- val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
- I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
- I2C_CONTROL_CNTL_START;
- SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
-
- while (exit_cnt < 5) {
- val64 = readq(&bar0->i2c_control);
- if (I2C_CONTROL_CNTL_END(val64)) {
- if (!(val64 & I2C_CONTROL_NACK))
- ret = 0;
- break;
- }
- msleep(50);
- exit_cnt++;
- }
- }
+ val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+ I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) |
+ I2C_CONTROL_CNTL_START;
+ SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
- if (sp->device_type == XFRAME_II_DEVICE) {
- int write_cnt = (cnt == 8) ? 0 : cnt;
- writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
-
- val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
- SPI_CONTROL_BYTECNT(write_cnt) |
- SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
- SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
- val64 |= SPI_CONTROL_REQ;
- SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
- while (exit_cnt < 5) {
- val64 = readq(&bar0->spi_control);
- if (val64 & SPI_CONTROL_NACK) {
- ret = 1;
- break;
- } else if (val64 & SPI_CONTROL_DONE) {
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->i2c_control);
+ if (I2C_CONTROL_CNTL_END(val64)) {
+ if (!(val64 & I2C_CONTROL_NACK))
ret = 0;
- break;
- }
- msleep(50);
- exit_cnt++;
+ break;
}
+ msleep(50);
+ exit_cnt++;
}
+
return ret;
}
@@ -4509,8 +4060,7 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
static int s2io_ethtool_geeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * data_buf)
{
- u32 i, valid;
- u64 data;
+ u32 data, i, valid;
nic_t *sp = dev->priv;
eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -4548,7 +4098,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
u8 * data_buf)
{
int len = eeprom->len, cnt = 0;
- u64 valid = 0, data;
+ u32 valid = 0, data;
nic_t *sp = dev->priv;
if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
@@ -4596,7 +4146,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
static int s2io_register_test(nic_t * sp, uint64_t * data)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- u64 val64 = 0, exp_val;
+ u64 val64 = 0;
int fail = 0;
val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -4612,11 +4162,7 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
val64 = readq(&bar0->rx_queue_cfg);
- if (sp->device_type == XFRAME_II_DEVICE)
- exp_val = 0x0404040404040404ULL;
- else
- exp_val = 0x0808080808080808ULL;
- if (val64 != exp_val) {
+ if (val64 != 0x0808080808080808ULL) {
fail = 1;
DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
}
@@ -4644,7 +4190,7 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
*data = fail;
- return fail;
+ return 0;
}
/**
@@ -4663,83 +4209,58 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
{
int fail = 0;
- u64 ret_data, org_4F0, org_7F0;
- u8 saved_4F0 = 0, saved_7F0 = 0;
- struct net_device *dev = sp->dev;
+ u32 ret_data;
/* Test Write Error at offset 0 */
- /* Note that SPI interface allows write access to all areas
- * of EEPROM. Hence doing all negative testing only for Xframe I.
- */
- if (sp->device_type == XFRAME_I_DEVICE)
- if (!write_eeprom(sp, 0, 0, 3))
- fail = 1;
-
- /* Save current values at offsets 0x4F0 and 0x7F0 */
- if (!read_eeprom(sp, 0x4F0, &org_4F0))
- saved_4F0 = 1;
- if (!read_eeprom(sp, 0x7F0, &org_7F0))
- saved_7F0 = 1;
+ if (!write_eeprom(sp, 0, 0, 3))
+ fail = 1;
/* Test Write at offset 4f0 */
- if (write_eeprom(sp, 0x4F0, 0x012345, 3))
+ if (write_eeprom(sp, 0x4F0, 0x01234567, 3))
fail = 1;
if (read_eeprom(sp, 0x4F0, &ret_data))
fail = 1;
- if (ret_data != 0x012345) {
- DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
+ if (ret_data != 0x01234567)
fail = 1;
- }
/* Reset the EEPROM data go FFFF */
- write_eeprom(sp, 0x4F0, 0xFFFFFF, 3);
+ write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3);
/* Test Write Request Error at offset 0x7c */
- if (sp->device_type == XFRAME_I_DEVICE)
- if (!write_eeprom(sp, 0x07C, 0, 3))
- fail = 1;
+ if (!write_eeprom(sp, 0x07C, 0, 3))
+ fail = 1;
- /* Test Write Request at offset 0x7f0 */
- if (write_eeprom(sp, 0x7F0, 0x012345, 3))
+ /* Test Write Request at offset 0x7fc */
+ if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
fail = 1;
- if (read_eeprom(sp, 0x7F0, &ret_data))
+ if (read_eeprom(sp, 0x7FC, &ret_data))
fail = 1;
- if (ret_data != 0x012345) {
- DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
+ if (ret_data != 0x01234567)
fail = 1;
- }
/* Reset the EEPROM data go FFFF */
- write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
-
- if (sp->device_type == XFRAME_I_DEVICE) {
- /* Test Write Error at offset 0x80 */
- if (!write_eeprom(sp, 0x080, 0, 3))
- fail = 1;
+ write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
- /* Test Write Error at offset 0xfc */
- if (!write_eeprom(sp, 0x0FC, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 0x80 */
+ if (!write_eeprom(sp, 0x080, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 0x100 */
- if (!write_eeprom(sp, 0x100, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 0xfc */
+ if (!write_eeprom(sp, 0x0FC, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 4ec */
- if (!write_eeprom(sp, 0x4EC, 0, 3))
- fail = 1;
- }
+ /* Test Write Error at offset 0x100 */
+ if (!write_eeprom(sp, 0x100, 0, 3))
+ fail = 1;
- /* Restore values at offsets 0x4F0 and 0x7F0 */
- if (saved_4F0)
- write_eeprom(sp, 0x4F0, org_4F0, 3);
- if (saved_7F0)
- write_eeprom(sp, 0x7F0, org_7F0, 3);
+ /* Test Write Error at offset 4ec */
+ if (!write_eeprom(sp, 0x4EC, 0, 3))
+ fail = 1;
*data = fail;
- return fail;
+ return 0;
}
/**
@@ -4821,7 +4342,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
- int cnt, iteration = 0, test_fail = 0;
+ int cnt, iteration = 0, test_pass = 0;
val64 = readq(&bar0->adapter_control);
val64 &= ~ADAPTER_ECC_EN;
@@ -4829,7 +4350,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
val64 = readq(&bar0->mc_rldram_test_ctrl);
val64 |= MC_RLDRAM_TEST_MODE;
- SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
+ writeq(val64, &bar0->mc_rldram_test_ctrl);
val64 = readq(&bar0->mc_rldram_mrs);
val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE;
@@ -4857,12 +4378,17 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
}
writeq(val64, &bar0->mc_rldram_test_d2);
- val64 = (u64) (0x0000003ffffe0100ULL);
+ val64 = (u64) (0x0000003fffff0000ULL);
writeq(val64, &bar0->mc_rldram_test_add);
- val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
- MC_RLDRAM_TEST_GO;
- SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
+
+ val64 = MC_RLDRAM_TEST_MODE;
+ writeq(val64, &bar0->mc_rldram_test_ctrl);
+
+ val64 |=
+ MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
+ MC_RLDRAM_TEST_GO;
+ writeq(val64, &bar0->mc_rldram_test_ctrl);
for (cnt = 0; cnt < 5; cnt++) {
val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4874,8 +4400,11 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
if (cnt == 5)
break;
- val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
- SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
+ val64 = MC_RLDRAM_TEST_MODE;
+ writeq(val64, &bar0->mc_rldram_test_ctrl);
+
+ val64 |= MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
+ writeq(val64, &bar0->mc_rldram_test_ctrl);
for (cnt = 0; cnt < 5; cnt++) {
val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4888,18 +4417,18 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
break;
val64 = readq(&bar0->mc_rldram_test_ctrl);
- if (!(val64 & MC_RLDRAM_TEST_PASS))
- test_fail = 1;
+ if (val64 & MC_RLDRAM_TEST_PASS)
+ test_pass = 1;
iteration++;
}
- *data = test_fail;
-
- /* Bring the adapter out of test mode */
- SPECIAL_REG_WRITE(0, &bar0->mc_rldram_test_ctrl, LF);
+ if (!test_pass)
+ *data = 1;
+ else
+ *data = 0;
- return test_fail;
+ return 0;
}
/**
@@ -5403,7 +4932,7 @@ static void s2io_card_down(nic_t * sp)
static int s2io_card_up(nic_t * sp)
{
- int i, ret = 0;
+ int i, ret;
mac_info_t *mac_control;
struct config_param *config;
struct net_device *dev = (struct net_device *) sp->dev;
@@ -5415,15 +4944,6 @@ static int s2io_card_up(nic_t * sp)
return -ENODEV;
}
- if (sp->intr_type == MSI)
- ret = s2io_enable_msi(sp);
- else if (sp->intr_type == MSI_X)
- ret = s2io_enable_msi_x(sp);
- if (ret) {
- DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
- sp->intr_type = INTA;
- }
-
/*
* Initializing the Rx buffers. For now we are considering only 1
* Rx ring and initializing buffers into 30 Rx blocks
@@ -5708,8 +5228,6 @@ static void s2io_init_pci(nic_t * sp)
MODULE_AUTHOR("Raghavendra Koushik ");
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
module_param(tx_fifo_num, int, 0);
module_param(rx_ring_num, int, 0);
module_param_array(tx_fifo_len, uint, NULL, 0);
@@ -5727,7 +5245,6 @@ module_param(bimodal, bool, 0);
module_param(indicate_max_pkts, int, 0);
#endif
module_param(rxsync_frequency, int, 0);
-module_param(intr_type, int, 0);
/**
* s2io_init_nic - Initialization of the adapter .
@@ -5757,16 +5274,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
mac_info_t *mac_control;
struct config_param *config;
int mode;
- u8 dev_intr_type = intr_type;
#ifdef CONFIG_S2IO_NAPI
- if (dev_intr_type != INTA) {
- DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
-is enabled. Defaulting to INTA\n");
- dev_intr_type = INTA;
- }
- else
- DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+ DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
#endif
if ((ret = pci_enable_device(pdev))) {
@@ -5793,35 +5303,10 @@ is enabled. Defaulting to INTA\n");
return -ENOMEM;
}
- if ((dev_intr_type == MSI_X) &&
- ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
- (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
- DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
-Defaulting to INTA\n");
- dev_intr_type = INTA;
- }
- if (dev_intr_type != MSI_X) {
- if (pci_request_regions(pdev, s2io_driver_name)) {
- DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
- pci_disable_device(pdev);
- return -ENODEV;
- }
- }
- else {
- if (!(request_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), s2io_driver_name))) {
- DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
- pci_disable_device(pdev);
- return -ENODEV;
- }
- if (!(request_mem_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2), s2io_driver_name))) {
- DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- pci_disable_device(pdev);
- return -ENODEV;
- }
+ if (pci_request_regions(pdev, s2io_driver_name)) {
+ DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+ pci_disable_device(pdev);
+ return -ENODEV;
}
dev = alloc_etherdev(sizeof(nic_t));
@@ -5844,7 +5329,6 @@ Defaulting to INTA\n");
sp->pdev = pdev;
sp->high_dma_flag = dma_flag;
sp->device_enabled_once = FALSE;
- sp->intr_type = dev_intr_type;
if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
(pdev->device == PCI_DEVICE_ID_HERC_UNI))
@@ -5852,7 +5336,6 @@ Defaulting to INTA\n");
else
sp->device_type = XFRAME_I_DEVICE;
-
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
@@ -6088,23 +5571,12 @@ Defaulting to INTA\n");
if (sp->device_type & XFRAME_II_DEVICE) {
DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
dev->name);
- DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+ DBG_PRINT(ERR_DBG, "(rev %d), %s",
get_xena_rev_id(sp->pdev),
s2io_driver_version);
#ifdef CONFIG_2BUFF_MODE
DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
#endif
- switch(sp->intr_type) {
- case INTA:
- DBG_PRINT(ERR_DBG, ", Intr type INTA");
- break;
- case MSI:
- DBG_PRINT(ERR_DBG, ", Intr type MSI");
- break;
- case MSI_X:
- DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
- break;
- }
DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -6123,23 +5595,12 @@ Defaulting to INTA\n");
} else {
DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
dev->name);
- DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+ DBG_PRINT(ERR_DBG, "(rev %d), %s",
get_xena_rev_id(sp->pdev),
s2io_driver_version);
#ifdef CONFIG_2BUFF_MODE
DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
#endif
- switch(sp->intr_type) {
- case INTA:
- DBG_PRINT(ERR_DBG, ", Intr type INTA");
- break;
- case MSI:
- DBG_PRINT(ERR_DBG, ", Intr type MSI");
- break;
- case MSI_X:
- DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
- break;
- }
DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
sp->def_mac_addr[0].mac_addr[0],
@@ -6183,14 +5644,7 @@ Defaulting to INTA\n");
mem_alloc_failed:
free_shared_mem(sp);
pci_disable_device(pdev);
- if (dev_intr_type != MSI_X)
- pci_release_regions(pdev);
- else {
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- release_mem_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2));
- }
+ pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
free_netdev(dev);
@@ -6224,14 +5678,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
iounmap(sp->bar0);
iounmap(sp->bar1);
pci_disable_device(pdev);
- if (sp->intr_type != MSI_X)
- pci_release_regions(pdev);
- else {
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- release_mem_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2));
- }
+ pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
free_netdev(dev);
}
diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h
index 1cc24b56760e..89151cb52181 100644
--- a/trunk/drivers/net/s2io.h
+++ b/trunk/drivers/net/s2io.h
@@ -652,30 +652,6 @@ typedef struct {
#define SMALL_BLK_CNT 30
#define LARGE_BLK_CNT 100
-/*
- * Structure to keep track of the MSI-X vectors and the corresponding
- * argument registered against each vector
- */
-#define MAX_REQUESTED_MSI_X 17
-struct s2io_msix_entry
-{
- u16 vector;
- u16 entry;
- void *arg;
-
- u8 type;
-#define MSIX_FIFO_TYPE 1
-#define MSIX_RING_TYPE 2
-
- u8 in_use;
-#define MSIX_REGISTERED_SUCCESS 0xAA
-};
-
-struct msix_info_st {
- u64 addr;
- u64 data;
-};
-
/* Structure representing one instance of the NIC */
struct s2io_nic {
#ifdef CONFIG_S2IO_NAPI
@@ -743,8 +719,13 @@ struct s2io_nic {
* a schedule task that will set the correct Link state once the
* NIC's PHY has stabilized after a state change.
*/
+#ifdef INIT_TQUEUE
+ struct tq_struct rst_timer_task;
+ struct tq_struct set_link_task;
+#else
struct work_struct rst_timer_task;
struct work_struct set_link_task;
+#endif
/* Flag that can be used to turn on or turn off the Rx checksum
* offload feature.
@@ -767,23 +748,10 @@ struct s2io_nic {
atomic_t card_state;
volatile unsigned long link_state;
struct vlan_group *vlgrp;
-#define MSIX_FLG 0xA5
- struct msix_entry *entries;
- struct s2io_msix_entry *s2io_entries;
- char desc1[35];
- char desc2[35];
-
- struct msix_info_st msix_info[0x3f];
-
#define XFRAME_I_DEVICE 1
#define XFRAME_II_DEVICE 2
u8 device_type;
-#define INTA 0
-#define MSI 1
-#define MSI_X 2
- u8 intr_type;
-
spinlock_t rx_lock;
atomic_t isr_cnt;
};
@@ -918,13 +886,6 @@ static int s2io_poll(struct net_device *dev, int *budget);
static void s2io_init_pci(nic_t * sp);
int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
static void s2io_alarm_handle(unsigned long data);
-static int s2io_enable_msi(nic_t *nic);
-static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t
-s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t
-s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
-int s2io_enable_msi_x(nic_t *nic);
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
@@ -933,5 +894,4 @@ int s2io_set_swapper(nic_t * sp);
static void s2io_card_down(nic_t *nic);
static int s2io_card_up(nic_t *nic);
int get_xena_rev_id(struct pci_dev *pdev);
-void restore_xmsi_data(nic_t *nic);
#endif /* _S2IO_H */
diff --git a/trunk/drivers/net/sb1250-mac.c b/trunk/drivers/net/sb1250-mac.c
index aa4ca1821759..7abd55a4fb21 100644
--- a/trunk/drivers/net/sb1250-mac.c
+++ b/trunk/drivers/net/sb1250-mac.c
@@ -10,7 +10,7 @@
* 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.
@@ -118,6 +118,8 @@ MODULE_PARM_DESC(int_timeout, "Timeout value");
********************************************************************* */
+typedef unsigned long sbmac_port_t;
+
typedef enum { sbmac_speed_auto, sbmac_speed_10,
sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
@@ -127,7 +129,7 @@ typedef enum { sbmac_duplex_auto, sbmac_duplex_half,
typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
-typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
+typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
sbmac_state_broken } sbmac_state_t;
@@ -142,13 +144,17 @@ typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
+#define SBMAC_READCSR(t) __raw_readq((unsigned long)t)
+#define SBMAC_WRITECSR(t,v) __raw_writeq(v, (unsigned long)t)
+
+
#define SBMAC_MAX_TXDESCR 32
#define SBMAC_MAX_RXDESCR 32
#define ETHER_ALIGN 2
#define ETHER_ADDR_LEN 6
-#define ENET_PACKET_SIZE 1518
-/*#define ENET_PACKET_SIZE 9216 */
+#define ENET_PACKET_SIZE 1518
+/*#define ENET_PACKET_SIZE 9216 */
/**********************************************************************
* DMA Descriptor structure
@@ -166,12 +172,12 @@ typedef unsigned long paddr_t;
********************************************************************* */
typedef struct sbmacdma_s {
-
- /*
+
+ /*
* This stuff is used to identify the channel and the registers
* associated with it.
*/
-
+
struct sbmac_softc *sbdma_eth; /* back pointer to associated MAC */
int sbdma_channel; /* channel number */
int sbdma_txdir; /* direction (1=transmit) */
@@ -181,21 +187,21 @@ typedef struct sbmacdma_s {
int sbdma_int_timeout; /* # usec rx/tx interrupt */
#endif
- volatile void __iomem *sbdma_config0; /* DMA config register 0 */
- volatile void __iomem *sbdma_config1; /* DMA config register 1 */
- volatile void __iomem *sbdma_dscrbase; /* Descriptor base address */
- volatile void __iomem *sbdma_dscrcnt; /* Descriptor count register */
- volatile void __iomem *sbdma_curdscr; /* current descriptor address */
-
+ sbmac_port_t sbdma_config0; /* DMA config register 0 */
+ sbmac_port_t sbdma_config1; /* DMA config register 1 */
+ sbmac_port_t sbdma_dscrbase; /* Descriptor base address */
+ sbmac_port_t sbdma_dscrcnt; /* Descriptor count register */
+ sbmac_port_t sbdma_curdscr; /* current descriptor address */
+
/*
* This stuff is for maintenance of the ring
*/
-
+
sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */
sbdmadscr_t *sbdma_dscrtable_end; /* end of descriptor table */
-
+
struct sk_buff **sbdma_ctxtable; /* context table, one per descr */
-
+
paddr_t sbdma_dscrtable_phys; /* and also the phys addr */
sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */
sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */
@@ -207,15 +213,15 @@ typedef struct sbmacdma_s {
********************************************************************* */
struct sbmac_softc {
-
+
/*
* Linux-specific things
*/
-
+
struct net_device *sbm_dev; /* pointer to linux device */
spinlock_t sbm_lock; /* spin lock */
struct timer_list sbm_timer; /* for monitoring MII */
- struct net_device_stats sbm_stats;
+ struct net_device_stats sbm_stats;
int sbm_devflags; /* current device flags */
int sbm_phy_oldbmsr;
@@ -223,31 +229,31 @@ struct sbmac_softc {
int sbm_phy_oldk1stsr;
int sbm_phy_oldlinkstat;
int sbm_buffersize;
-
+
unsigned char sbm_phys[2];
-
+
/*
* Controller-specific things
*/
-
- volatile void __iomem *sbm_base; /* MAC's base address */
+
+ unsigned long sbm_base; /* MAC's base address */
sbmac_state_t sbm_state; /* current state */
-
- volatile void __iomem *sbm_macenable; /* MAC Enable Register */
- volatile void __iomem *sbm_maccfg; /* MAC Configuration Register */
- volatile void __iomem *sbm_fifocfg; /* FIFO configuration register */
- volatile void __iomem *sbm_framecfg; /* Frame configuration register */
- volatile void __iomem *sbm_rxfilter; /* receive filter register */
- volatile void __iomem *sbm_isr; /* Interrupt status register */
- volatile void __iomem *sbm_imr; /* Interrupt mask register */
- volatile void __iomem *sbm_mdio; /* MDIO register */
-
+
+ sbmac_port_t sbm_macenable; /* MAC Enable Register */
+ sbmac_port_t sbm_maccfg; /* MAC Configuration Register */
+ sbmac_port_t sbm_fifocfg; /* FIFO configuration register */
+ sbmac_port_t sbm_framecfg; /* Frame configuration register */
+ sbmac_port_t sbm_rxfilter; /* receive filter register */
+ sbmac_port_t sbm_isr; /* Interrupt status register */
+ sbmac_port_t sbm_imr; /* Interrupt mask register */
+ sbmac_port_t sbm_mdio; /* MDIO register */
+
sbmac_speed_t sbm_speed; /* current speed */
sbmac_duplex_t sbm_duplex; /* current duplex */
sbmac_fc_t sbm_fc; /* current flow control setting */
-
+
unsigned char sbm_hwaddr[ETHER_ADDR_LEN];
-
+
sbmacdma_t sbm_txdma; /* for now, only use channel 0 */
sbmacdma_t sbm_rxdma;
int rx_hw_checksum;
@@ -296,7 +302,6 @@ static void sbmac_set_rx_mode(struct net_device *dev);
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int sbmac_close(struct net_device *dev);
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
-static int sbmac_mii_probe(struct net_device *dev);
static void sbmac_mii_sync(struct sbmac_softc *s);
static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);
@@ -434,9 +439,6 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
#define MII_BMCR 0x00 /* Basic mode control register (rw) */
#define MII_BMSR 0x01 /* Basic mode status register (ro) */
-#define MII_PHYIDR1 0x02
-#define MII_PHYIDR2 0x03
-
#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
#define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
@@ -448,13 +450,13 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
/**********************************************************************
* SBMAC_MII_SYNC(s)
- *
+ *
* Synchronize with the MII - send a pattern of bits to the MII
* that will guarantee that it is ready to accept a command.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -465,25 +467,25 @@ static void sbmac_mii_sync(struct sbmac_softc *s)
uint64_t bits;
int mac_mdio_genc;
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
-
+ mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+
bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
-
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
-
+
+ SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+
for (cnt = 0; cnt < 32; cnt++) {
- __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
+ SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
}
}
/**********************************************************************
* SBMAC_MII_SENDDATA(s,data,bitcnt)
- *
+ *
* Send some bits to the MII. The bits to be sent are right-
* justified in the 'data' parameter.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* data - data to send
* bitcnt - number of bits to send
@@ -496,20 +498,20 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
unsigned int curmask;
int mac_mdio_genc;
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
-
+ mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+
bits = M_MAC_MDIO_DIR_OUTPUT;
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
-
+ SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+
curmask = 1 << (bitcnt - 1);
-
+
for (i = 0; i < bitcnt; i++) {
if (data & curmask)
bits |= M_MAC_MDIO_OUT;
else bits &= ~M_MAC_MDIO_OUT;
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+ SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
+ SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
curmask >>= 1;
}
}
@@ -518,14 +520,14 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
/**********************************************************************
* SBMAC_MII_READ(s,phyaddr,regidx)
- *
+ *
* Read a PHY register.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* phyaddr - PHY's address
* regidx = index of register to read
- *
+ *
* Return value:
* value read, or 0 if an error occurred.
********************************************************************* */
@@ -541,9 +543,9 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
* Synchronize ourselves so that the PHY knows the next
* thing coming down is a command
*/
-
+
sbmac_mii_sync(s);
-
+
/*
* Send the data to the PHY. The sequence is
* a "start" command (2 bits)
@@ -551,55 +553,59 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
* the PHY addr (5 bits)
* the register index (5 bits)
*/
-
+
sbmac_mii_senddata(s,MII_COMMAND_START, 2);
sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
sbmac_mii_senddata(s,phyaddr, 5);
sbmac_mii_senddata(s,regidx, 5);
-
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
-
- /*
+
+ mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+
+ /*
* Switch the port around without a clock transition.
*/
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
-
+ SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
/*
* Send out a clock pulse to signal we want the status
*/
-
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
-
- /*
+
+ SBMAC_WRITECSR(s->sbm_mdio,
+ M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
+ SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
+ /*
* If an error occurred, the PHY will signal '1' back
*/
- error = __raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN;
-
- /*
+ error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN;
+
+ /*
* Issue an 'idle' clock pulse, but keep the direction
* the same.
*/
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
-
+ SBMAC_WRITECSR(s->sbm_mdio,
+ M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
+ SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
regval = 0;
-
+
for (idx = 0; idx < 16; idx++) {
regval <<= 1;
-
+
if (error == 0) {
- if (__raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN)
+ if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
regval |= 1;
}
-
- __raw_writeq(M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
- __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
+ SBMAC_WRITECSR(s->sbm_mdio,
+ M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc);
+ SBMAC_WRITECSR(s->sbm_mdio,
+ M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
}
-
+
/* Switch back to output */
- __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
-
+ SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
+
if (error == 0)
return regval;
return 0;
@@ -608,15 +614,15 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
/**********************************************************************
* SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
- *
+ *
* Write a value to a PHY register.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* phyaddr - PHY to use
* regidx - register within the PHY
* regval - data to write to register
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -627,7 +633,7 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
int mac_mdio_genc;
sbmac_mii_sync(s);
-
+
sbmac_mii_senddata(s,MII_COMMAND_START,2);
sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
sbmac_mii_senddata(s,phyaddr, 5);
@@ -635,27 +641,27 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
sbmac_mii_senddata(s,regval,16);
- mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
- __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+ SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
}
/**********************************************************************
* SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
- *
+ *
* Initialize a DMA channel context. Since there are potentially
* eight DMA channels per MAC, it's nice to do this in a standard
- * way.
- *
- * Input parameters:
+ * way.
+ *
+ * Input parameters:
* d - sbmacdma_t structure (DMA channel context)
* s - sbmac_softc structure (pointer to a MAC)
* chan - channel number (0..1 right now)
* txrx - Identifies DMA_TX or DMA_RX for channel direction
* maxdescr - number of descriptors
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -666,87 +672,101 @@ static void sbdma_initctx(sbmacdma_t *d,
int txrx,
int maxdescr)
{
- /*
- * Save away interesting stuff in the structure
+ /*
+ * Save away interesting stuff in the structure
*/
-
+
d->sbdma_eth = s;
d->sbdma_channel = chan;
d->sbdma_txdir = txrx;
-
+
#if 0
/* RMON clearing */
s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
#endif
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)));
- __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)));
-
- /*
- * initialize register pointers
- */
-
- d->sbdma_config0 =
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
+ SBMAC_WRITECSR(IOADDR(
+ A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
+
+ /*
+ * initialize register pointers
+ */
+
+ d->sbdma_config0 =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
- d->sbdma_config1 =
+ d->sbdma_config1 =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
- d->sbdma_dscrbase =
+ d->sbdma_dscrbase =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
- d->sbdma_dscrcnt =
+ d->sbdma_dscrcnt =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
- d->sbdma_curdscr =
+ d->sbdma_curdscr =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
-
+
/*
* Allocate memory for the ring
*/
-
+
d->sbdma_maxdescr = maxdescr;
-
- d->sbdma_dscrtable = (sbdmadscr_t *)
- kmalloc((d->sbdma_maxdescr+1)*sizeof(sbdmadscr_t), GFP_KERNEL);
-
- /*
- * The descriptor table must be aligned to at least 16 bytes or the
- * MAC will corrupt it.
- */
- d->sbdma_dscrtable = (sbdmadscr_t *)
- ALIGN((unsigned long)d->sbdma_dscrtable, sizeof(sbdmadscr_t));
-
+
+ d->sbdma_dscrtable = (sbdmadscr_t *)
+ kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
+
memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
-
+
d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
-
+
d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
-
+
/*
* And context table
*/
-
- d->sbdma_ctxtable = (struct sk_buff **)
+
+ d->sbdma_ctxtable = (struct sk_buff **)
kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
-
+
memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
-
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Setup Rx/Tx DMA coalescing defaults
@@ -757,7 +777,7 @@ static void sbdma_initctx(sbmacdma_t *d,
} else {
d->sbdma_int_pktcnt = 1;
}
-
+
if ( int_timeout ) {
d->sbdma_int_timeout = int_timeout;
} else {
@@ -769,13 +789,13 @@ static void sbdma_initctx(sbmacdma_t *d,
/**********************************************************************
* SBDMA_CHANNEL_START(d)
- *
+ *
* Initialize the hardware registers for a DMA channel.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel to init (context must be previously init'd
* rxtx - DMA_RX or DMA_TX depending on what type of channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -785,21 +805,24 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
/*
* Turn on the DMA channel
*/
-
+
#ifdef CONFIG_SBMAC_COALESCE
- __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
- 0, d->sbdma_config1);
- __raw_writeq(M_DMA_EOP_INT_EN |
+ SBMAC_WRITECSR(d->sbdma_config1,
+ V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
+ 0);
+ SBMAC_WRITECSR(d->sbdma_config0,
+ M_DMA_EOP_INT_EN |
V_DMA_RINGSZ(d->sbdma_maxdescr) |
V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
- 0, d->sbdma_config0);
+ 0);
#else
- __raw_writeq(0, d->sbdma_config1);
- __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
- 0, d->sbdma_config0);
+ SBMAC_WRITECSR(d->sbdma_config1,0);
+ SBMAC_WRITECSR(d->sbdma_config0,
+ V_DMA_RINGSZ(d->sbdma_maxdescr) |
+ 0);
#endif
- __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
+ SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
/*
* Initialize ring pointers
@@ -811,12 +834,12 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
/**********************************************************************
* SBDMA_CHANNEL_STOP(d)
- *
+ *
* Initialize the hardware registers for a DMA channel.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel to init (context must be previously init'd
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -826,44 +849,44 @@ static void sbdma_channel_stop(sbmacdma_t *d)
/*
* Turn off the DMA channel
*/
-
- __raw_writeq(0, d->sbdma_config1);
-
- __raw_writeq(0, d->sbdma_dscrbase);
-
- __raw_writeq(0, d->sbdma_config0);
-
+
+ SBMAC_WRITECSR(d->sbdma_config1,0);
+
+ SBMAC_WRITECSR(d->sbdma_dscrbase,0);
+
+ SBMAC_WRITECSR(d->sbdma_config0,0);
+
/*
* Zero ring pointers
*/
-
- d->sbdma_addptr = NULL;
- d->sbdma_remptr = NULL;
+
+ d->sbdma_addptr = 0;
+ d->sbdma_remptr = 0;
}
static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
{
unsigned long addr;
unsigned long newaddr;
-
+
addr = (unsigned long) skb->data;
-
+
newaddr = (addr + power2 - 1) & ~(power2 - 1);
-
+
skb_reserve(skb,newaddr-addr+offset);
}
/**********************************************************************
* SBDMA_ADD_RCVBUFFER(d,sb)
- *
+ *
* Add a buffer to the specified DMA channel. For receive channels,
* this queues a buffer for inbound packets.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel descriptor
* sb - sk_buff to add, or NULL if we should allocate one
- *
+ *
* Return value:
* 0 if buffer could not be added (ring is full)
* 1 if buffer added successfully
@@ -876,24 +899,24 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
sbdmadscr_t *nextdsc;
struct sk_buff *sb_new = NULL;
int pktsize = ENET_PACKET_SIZE;
-
+
/* get pointer to our current place in the ring */
-
+
dsc = d->sbdma_addptr;
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-
+
/*
* figure out if the ring is full - if the next descriptor
* is the same as the one that we're going to remove from
* the ring, the ring is full
*/
-
+
if (nextdsc == d->sbdma_remptr) {
return -ENOSPC;
}
- /*
- * Allocate a sk_buff if we don't already have one.
+ /*
+ * Allocate a sk_buff if we don't already have one.
* If we do have an sk_buff, reset it so that it's empty.
*
* Note: sk_buffs don't seem to be guaranteed to have any sort
@@ -902,7 +925,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
*
* 1. the data does not start in the middle of a cache line.
* 2. The data does not end in the middle of a cache line
- * 3. The buffer can be aligned such that the IP addresses are
+ * 3. The buffer can be aligned such that the IP addresses are
* naturally aligned.
*
* Remember, the SOCs MAC writes whole cache lines at a time,
@@ -910,7 +933,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
* data portion starts in the middle of a cache line, the SOC
* DMA will trash the beginning (and ending) portions.
*/
-
+
if (sb == NULL) {
sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
if (sb_new == NULL) {
@@ -926,22 +949,23 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
}
else {
sb_new = sb;
- /*
+ /*
* nothing special to reinit buffer, it's already aligned
* and sb->data already points to a good place.
*/
}
-
+
/*
- * fill in the descriptor
+ * fill in the descriptor
*/
-
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Do not interrupt per DMA transfer.
*/
dsc->dscr_a = virt_to_phys(sb_new->data) |
- V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0;
+ V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
+ 0;
#else
dsc->dscr_a = virt_to_phys(sb_new->data) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
@@ -950,38 +974,38 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
/* receiving: no options */
dsc->dscr_b = 0;
-
+
/*
- * fill in the context
+ * fill in the context
*/
-
+
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
-
- /*
- * point at next packet
+
+ /*
+ * point at next packet
*/
-
+
d->sbdma_addptr = nextdsc;
-
- /*
+
+ /*
* Give the buffer to the DMA engine.
*/
-
- __raw_writeq(1, d->sbdma_dscrcnt);
-
+
+ SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
+
return 0; /* we did it */
}
/**********************************************************************
* SBDMA_ADD_TXBUFFER(d,sb)
- *
+ *
* Add a transmit buffer to the specified DMA channel, causing a
* transmit to start.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel descriptor
* sb - sk_buff to add
- *
+ *
* Return value:
* 0 transmit queued successfully
* otherwise error code
@@ -995,70 +1019,70 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
uint64_t phys;
uint64_t ncb;
int length;
-
+
/* get pointer to our current place in the ring */
-
+
dsc = d->sbdma_addptr;
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-
+
/*
* figure out if the ring is full - if the next descriptor
* is the same as the one that we're going to remove from
* the ring, the ring is full
*/
-
+
if (nextdsc == d->sbdma_remptr) {
return -ENOSPC;
}
-
+
/*
* Under Linux, it's not necessary to copy/coalesce buffers
* like it is on NetBSD. We think they're all contiguous,
* but that may not be true for GBE.
*/
-
+
length = sb->len;
-
+
/*
* fill in the descriptor. Note that the number of cache
* blocks in the descriptor is the number of blocks
* *spanned*, so we need to add in the offset (if any)
* while doing the calculation.
*/
-
+
phys = virt_to_phys(sb->data);
ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
- dsc->dscr_a = phys |
+ dsc->dscr_a = phys |
V_DMA_DSCRA_A_SIZE(ncb) |
#ifndef CONFIG_SBMAC_COALESCE
M_DMA_DSCRA_INTERRUPT |
#endif
M_DMA_ETHTX_SOP;
-
+
/* transmitting: set outbound options and length */
dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
V_DMA_DSCRB_PKT_SIZE(length);
-
+
/*
- * fill in the context
+ * fill in the context
*/
-
+
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
-
- /*
- * point at next packet
+
+ /*
+ * point at next packet
*/
-
+
d->sbdma_addptr = nextdsc;
-
- /*
+
+ /*
* Give the buffer to the DMA engine.
*/
-
- __raw_writeq(1, d->sbdma_dscrcnt);
-
+
+ SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
+
return 0; /* we did it */
}
@@ -1067,12 +1091,12 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
/**********************************************************************
* SBDMA_EMPTYRING(d)
- *
+ *
* Free all allocated sk_buffs on the specified DMA channel;
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1081,7 +1105,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
{
int idx;
struct sk_buff *sb;
-
+
for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
sb = d->sbdma_ctxtable[idx];
if (sb) {
@@ -1094,13 +1118,13 @@ static void sbdma_emptyring(sbmacdma_t *d)
/**********************************************************************
* SBDMA_FILLRING(d)
- *
+ *
* Fill the specified DMA channel (must be receive channel)
* with sk_buffs
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1108,7 +1132,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
static void sbdma_fillring(sbmacdma_t *d)
{
int idx;
-
+
for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
if (sbdma_add_rcvbuffer(d,NULL) != 0)
break;
@@ -1118,16 +1142,16 @@ static void sbdma_fillring(sbmacdma_t *d)
/**********************************************************************
* SBDMA_RX_PROCESS(sc,d)
- *
- * Process "completed" receive buffers on the specified DMA channel.
+ *
+ * Process "completed" receive buffers on the specified DMA channel.
* Note that this isn't really ideal for priority channels, since
- * it processes all of the packets on a given channel before
- * returning.
+ * it processes all of the packets on a given channel before
+ * returning.
*
- * Input parameters:
+ * Input parameters:
* sc - softc structure
* d - DMA channel context
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1139,56 +1163,56 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sbdmadscr_t *dsc;
struct sk_buff *sb;
int len;
-
+
for (;;) {
- /*
+ /*
* figure out where we are (as an index) and where
* the hardware is (also as an index)
*
- * This could be done faster if (for example) the
+ * This could be done faster if (for example) the
* descriptor table was page-aligned and contiguous in
* both virtual and physical memory -- you could then
* just compare the low-order bits of the virtual address
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
*/
-
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
- hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+ hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
-
+
/*
* If they're the same, that means we've processed all
* of the descriptors up to (but not including) the one that
* the hardware is working on right now.
*/
-
+
if (curidx == hwidx)
break;
-
+
/*
* Otherwise, get the packet's sk_buff ptr back
*/
-
+
dsc = &(d->sbdma_dscrtable[curidx]);
sb = d->sbdma_ctxtable[curidx];
d->sbdma_ctxtable[curidx] = NULL;
-
+
len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
-
+
/*
* Check packet status. If good, process it.
* If not, silently drop it and put it back on the
* receive ring.
*/
-
+
if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
-
+
/*
* Add a new buffer to replace the old one. If we fail
* to allocate a buffer, we're going to drop this
* packet and put it right back on the receive ring.
*/
-
+
if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
sc->sbm_stats.rx_dropped++;
sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
@@ -1197,7 +1221,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* Set length into the packet
*/
skb_put(sb,len);
-
+
/*
* Buffer has been replaced on the
* receive ring. Pass the buffer to
@@ -1216,7 +1240,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sb->ip_summed = CHECKSUM_NONE;
}
}
-
+
netif_rx(sb);
}
} else {
@@ -1227,14 +1251,14 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sc->sbm_stats.rx_errors++;
sbdma_add_rcvbuffer(d,sb);
}
-
-
- /*
+
+
+ /*
* .. and advance to the next buffer.
*/
-
+
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+
}
}
@@ -1242,17 +1266,17 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
/**********************************************************************
* SBDMA_TX_PROCESS(sc,d)
- *
- * Process "completed" transmit buffers on the specified DMA channel.
+ *
+ * Process "completed" transmit buffers on the specified DMA channel.
* This is normally called within the interrupt service routine.
* Note that this isn't really ideal for priority channels, since
- * it processes all of the packets on a given channel before
- * returning.
+ * it processes all of the packets on a given channel before
+ * returning.
*
- * Input parameters:
+ * Input parameters:
* sc - softc structure
* d - DMA channel context
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1266,21 +1290,21 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
unsigned long flags;
spin_lock_irqsave(&(sc->sbm_lock), flags);
-
+
for (;;) {
- /*
+ /*
* figure out where we are (as an index) and where
* the hardware is (also as an index)
*
- * This could be done faster if (for example) the
+ * This could be done faster if (for example) the
* descriptor table was page-aligned and contiguous in
* both virtual and physical memory -- you could then
* just compare the low-order bits of the virtual address
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
*/
-
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
- hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+ hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
/*
@@ -1288,75 +1312,75 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* of the descriptors up to (but not including) the one that
* the hardware is working on right now.
*/
-
+
if (curidx == hwidx)
break;
-
+
/*
* Otherwise, get the packet's sk_buff ptr back
*/
-
+
dsc = &(d->sbdma_dscrtable[curidx]);
sb = d->sbdma_ctxtable[curidx];
d->sbdma_ctxtable[curidx] = NULL;
-
+
/*
* Stats
*/
-
+
sc->sbm_stats.tx_bytes += sb->len;
sc->sbm_stats.tx_packets++;
-
+
/*
* for transmits, we just free buffers.
*/
-
+
dev_kfree_skb_irq(sb);
-
- /*
+
+ /*
* .. and advance to the next buffer.
*/
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+
}
-
+
/*
* Decide if we should wake up the protocol or not.
* Other drivers seem to do this when we reach a low
* watermark on the transmit queue.
*/
-
+
netif_wake_queue(d->sbdma_eth->sbm_dev);
-
+
spin_unlock_irqrestore(&(sc->sbm_lock), flags);
-
+
}
/**********************************************************************
* SBMAC_INITCTX(s)
- *
+ *
* Initialize an Ethernet context structure - this is called
* once per MAC on the 1250. Memory is allocated here, so don't
* call it again from inside the ioctl routines that bring the
* interface up/down
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac context structure
- *
+ *
* Return value:
* 0
********************************************************************* */
static int sbmac_initctx(struct sbmac_softc *s)
{
-
- /*
- * figure out the addresses of some ports
+
+ /*
+ * figure out the addresses of some ports
*/
-
+
s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
s->sbm_maccfg = s->sbm_base + R_MAC_CFG;
s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG;
@@ -1373,29 +1397,29 @@ static int sbmac_initctx(struct sbmac_softc *s)
s->sbm_phy_oldanlpar = 0;
s->sbm_phy_oldk1stsr = 0;
s->sbm_phy_oldlinkstat = 0;
-
+
/*
* Initialize the DMA channels. Right now, only one per MAC is used
* Note: Only do this _once_, as it allocates memory from the kernel!
*/
-
+
sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
-
+
/*
* initial state is OFF
*/
-
+
s->sbm_state = sbmac_state_off;
-
+
/*
* Initial speed is (XXX TEMP) 10MBit/s HDX no FC
*/
-
+
s->sbm_speed = sbmac_speed_10;
s->sbm_duplex = sbmac_duplex_half;
s->sbm_fc = sbmac_fc_disabled;
-
+
return 0;
}
@@ -1406,7 +1430,7 @@ static void sbdma_uninitctx(struct sbmacdma_s *d)
kfree(d->sbdma_dscrtable);
d->sbdma_dscrtable = NULL;
}
-
+
if (d->sbdma_ctxtable) {
kfree(d->sbdma_ctxtable);
d->sbdma_ctxtable = NULL;
@@ -1423,12 +1447,12 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
/**********************************************************************
* SBMAC_CHANNEL_START(s)
- *
+ *
* Start packet processing on this MAC.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1436,49 +1460,49 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
static void sbmac_channel_start(struct sbmac_softc *s)
{
uint64_t reg;
- volatile void __iomem *port;
+ sbmac_port_t port;
uint64_t cfg,fifo,framecfg;
int idx, th_value;
-
+
/*
* Don't do this if running
*/
if (s->sbm_state == sbmac_state_on)
return;
-
+
/*
* Bring the controller out of reset, but leave it off.
*/
-
- __raw_writeq(0, s->sbm_macenable);
-
+
+ SBMAC_WRITECSR(s->sbm_macenable,0);
+
/*
* Ignore all received packets
*/
-
- __raw_writeq(0, s->sbm_rxfilter);
-
- /*
+
+ SBMAC_WRITECSR(s->sbm_rxfilter,0);
+
+ /*
* Calculate values for various control registers.
*/
-
+
cfg = M_MAC_RETRY_EN |
- M_MAC_TX_HOLD_SOP_EN |
+ M_MAC_TX_HOLD_SOP_EN |
V_MAC_TX_PAUSE_CNT_16K |
M_MAC_AP_STAT_EN |
M_MAC_FAST_SYNC |
M_MAC_SS_EN |
0;
-
- /*
+
+ /*
* Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
* and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
* Use a larger RD_THRSH for gigabit
*/
- if (periph_rev >= 2)
+ if (periph_rev >= 2)
th_value = 64;
- else
+ else
th_value = 28;
fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
@@ -1496,51 +1520,51 @@ static void sbmac_channel_start(struct sbmac_softc *s)
V_MAC_BACKOFF_SEL(1);
/*
- * Clear out the hash address map
+ * Clear out the hash address map
*/
-
+
port = s->sbm_base + R_MAC_HASH_BASE;
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
}
-
+
/*
* Clear out the exact-match table
*/
-
+
port = s->sbm_base + R_MAC_ADDR_BASE;
for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
}
-
+
/*
* Clear out the DMA Channel mapping table registers
*/
-
+
port = s->sbm_base + R_MAC_CHUP0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
}
port = s->sbm_base + R_MAC_CHLO0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
}
-
+
/*
* Program the hardware address. It goes into the hardware-address
* register as well as the first filter register.
*/
-
+
reg = sbmac_addr2reg(s->sbm_hwaddr);
-
+
port = s->sbm_base + R_MAC_ADDR_BASE;
- __raw_writeq(reg, port);
+ SBMAC_WRITECSR(port,reg);
port = s->sbm_base + R_MAC_ETHERNET_ADDR;
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -1549,105 +1573,108 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* destination address in the R_MAC_ETHERNET_ADDR register.
* Set the value to zero.
*/
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
#else
- __raw_writeq(reg, port);
+ SBMAC_WRITECSR(port,reg);
#endif
-
+
/*
* Set the receive filter for no packets, and write values
* to the various config registers
*/
-
- __raw_writeq(0, s->sbm_rxfilter);
- __raw_writeq(0, s->sbm_imr);
- __raw_writeq(framecfg, s->sbm_framecfg);
- __raw_writeq(fifo, s->sbm_fifocfg);
- __raw_writeq(cfg, s->sbm_maccfg);
-
+
+ SBMAC_WRITECSR(s->sbm_rxfilter,0);
+ SBMAC_WRITECSR(s->sbm_imr,0);
+ SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
+ SBMAC_WRITECSR(s->sbm_fifocfg,fifo);
+ SBMAC_WRITECSR(s->sbm_maccfg,cfg);
+
/*
* Initialize DMA channels (rings should be ok now)
*/
-
+
sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
-
+
/*
* Configure the speed, duplex, and flow control
*/
sbmac_set_speed(s,s->sbm_speed);
sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
-
+
/*
* Fill the receive ring
*/
-
+
sbdma_fillring(&(s->sbm_rxdma));
-
- /*
+
+ /*
* Turn on the rest of the bits in the enable register
- */
-
- __raw_writeq(M_MAC_RXDMA_EN0 |
+ */
+
+ SBMAC_WRITECSR(s->sbm_macenable,
+ M_MAC_RXDMA_EN0 |
M_MAC_TXDMA_EN0 |
M_MAC_RX_ENABLE |
- M_MAC_TX_ENABLE, s->sbm_macenable);
-
-
+ M_MAC_TX_ENABLE);
+
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
*/
- __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
- ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
+ SBMAC_WRITECSR(s->sbm_imr,
+ ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+ ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
#else
/*
* Accept any kind of interrupt on TX and RX DMA channel 0
*/
- __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
- (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
+ SBMAC_WRITECSR(s->sbm_imr,
+ (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
+ (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
#endif
-
- /*
- * Enable receiving unicasts and broadcasts
+
+ /*
+ * Enable receiving unicasts and broadcasts
*/
-
- __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
-
+
+ SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
+
/*
- * we're running now.
+ * we're running now.
*/
-
+
s->sbm_state = sbmac_state_on;
-
- /*
- * Program multicast addresses
+
+ /*
+ * Program multicast addresses
*/
-
+
sbmac_setmulti(s);
-
- /*
- * If channel was in promiscuous mode before, turn that on
+
+ /*
+ * If channel was in promiscuous mode before, turn that on
*/
-
+
if (s->sbm_devflags & IFF_PROMISC) {
sbmac_promiscuous_mode(s,1);
}
-
+
}
/**********************************************************************
* SBMAC_CHANNEL_STOP(s)
- *
+ *
* Stop packet processing on this MAC.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1655,49 +1682,49 @@ static void sbmac_channel_start(struct sbmac_softc *s)
static void sbmac_channel_stop(struct sbmac_softc *s)
{
/* don't do this if already stopped */
-
+
if (s->sbm_state == sbmac_state_off)
return;
-
+
/* don't accept any packets, disable all interrupts */
-
- __raw_writeq(0, s->sbm_rxfilter);
- __raw_writeq(0, s->sbm_imr);
-
+
+ SBMAC_WRITECSR(s->sbm_rxfilter,0);
+ SBMAC_WRITECSR(s->sbm_imr,0);
+
/* Turn off ticker */
-
+
/* XXX */
-
+
/* turn off receiver and transmitter */
-
- __raw_writeq(0, s->sbm_macenable);
-
+
+ SBMAC_WRITECSR(s->sbm_macenable,0);
+
/* We're stopped now. */
-
+
s->sbm_state = sbmac_state_off;
-
+
/*
* Stop DMA channels (rings should be ok now)
*/
-
+
sbdma_channel_stop(&(s->sbm_rxdma));
sbdma_channel_stop(&(s->sbm_txdma));
-
+
/* Empty the receive and transmit rings */
-
+
sbdma_emptyring(&(s->sbm_rxdma));
sbdma_emptyring(&(s->sbm_txdma));
-
+
}
/**********************************************************************
* SBMAC_SET_CHANNEL_STATE(state)
- *
+ *
* Set the channel's state ON or OFF
- *
- * Input parameters:
+ *
+ * Input parameters:
* state - new state
- *
+ *
* Return value:
* old state
********************************************************************* */
@@ -1705,43 +1732,43 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
sbmac_state_t state)
{
sbmac_state_t oldstate = sc->sbm_state;
-
+
/*
* If same as previous state, return
*/
-
+
if (state == oldstate) {
return oldstate;
}
-
+
/*
- * If new state is ON, turn channel on
+ * If new state is ON, turn channel on
*/
-
+
if (state == sbmac_state_on) {
sbmac_channel_start(sc);
}
else {
sbmac_channel_stop(sc);
}
-
+
/*
* Return previous state
*/
-
+
return oldstate;
}
/**********************************************************************
* SBMAC_PROMISCUOUS_MODE(sc,onoff)
- *
+ *
* Turn on or off promiscuous mode
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
* onoff - 1 to turn on, 0 to turn off
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1749,30 +1776,30 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
{
uint64_t reg;
-
+
if (sc->sbm_state != sbmac_state_on)
return;
-
+
if (onoff) {
- reg = __raw_readq(sc->sbm_rxfilter);
+ reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg |= M_MAC_ALLPKT_EN;
- __raw_writeq(reg, sc->sbm_rxfilter);
- }
+ SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ }
else {
- reg = __raw_readq(sc->sbm_rxfilter);
+ reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg &= ~M_MAC_ALLPKT_EN;
- __raw_writeq(reg, sc->sbm_rxfilter);
+ SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
}
}
/**********************************************************************
* SBMAC_SETIPHDR_OFFSET(sc,onoff)
- *
+ *
* Set the iphdr offset as 15 assuming ethernet encapsulation
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1780,12 +1807,12 @@ static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
{
uint64_t reg;
-
+
/* Hard code the off set to 15 for now */
- reg = __raw_readq(sc->sbm_rxfilter);
+ reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
- __raw_writeq(reg, sc->sbm_rxfilter);
-
+ SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+
/* read system identification to determine revision */
if (periph_rev >= 2) {
sc->rx_hw_checksum = ENABLE;
@@ -1797,13 +1824,13 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
/**********************************************************************
* SBMAC_ADDR2REG(ptr)
- *
+ *
* Convert six bytes into the 64-bit register value that
* we typically write into the SBMAC's address/mcast registers
- *
- * Input parameters:
+ *
+ * Input parameters:
* ptr - pointer to 6 bytes
- *
+ *
* Return value:
* register value
********************************************************************* */
@@ -1811,35 +1838,35 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
static uint64_t sbmac_addr2reg(unsigned char *ptr)
{
uint64_t reg = 0;
-
+
ptr += 6;
-
- reg |= (uint64_t) *(--ptr);
+
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
-
+ reg |= (uint64_t) *(--ptr);
+
return reg;
}
/**********************************************************************
* SBMAC_SET_SPEED(s,speed)
- *
+ *
* Configure LAN speed for the specified MAC.
* Warning: must be called when MAC is off!
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* speed - speed to set MAC to (see sbmac_speed_t enum)
- *
+ *
* Return value:
* 1 if successful
* 0 indicates invalid parameters
@@ -1853,31 +1880,31 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
/*
* Save new current values
*/
-
+
s->sbm_speed = speed;
-
+
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
/*
- * Read current register values
+ * Read current register values
*/
-
- cfg = __raw_readq(s->sbm_maccfg);
- framecfg = __raw_readq(s->sbm_framecfg);
-
+
+ cfg = SBMAC_READCSR(s->sbm_maccfg);
+ framecfg = SBMAC_READCSR(s->sbm_framecfg);
+
/*
* Mask out the stuff we want to change
*/
-
+
cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
M_MAC_SLOT_SIZE);
-
+
/*
* Now add in the new bits
*/
-
+
switch (speed) {
case sbmac_speed_10:
framecfg |= V_MAC_IFG_RX_10 |
@@ -1886,7 +1913,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_10;
cfg |= V_MAC_SPEED_SEL_10MBPS;
break;
-
+
case sbmac_speed_100:
framecfg |= V_MAC_IFG_RX_100 |
V_MAC_IFG_TX_100 |
@@ -1894,7 +1921,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_100;
cfg |= V_MAC_SPEED_SEL_100MBPS ;
break;
-
+
case sbmac_speed_1000:
framecfg |= V_MAC_IFG_RX_1000 |
V_MAC_IFG_TX_1000 |
@@ -1902,34 +1929,34 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_1000;
cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
break;
-
+
case sbmac_speed_auto: /* XXX not implemented */
/* fall through */
default:
return 0;
}
-
+
/*
- * Send the bits back to the hardware
+ * Send the bits back to the hardware
*/
-
- __raw_writeq(framecfg, s->sbm_framecfg);
- __raw_writeq(cfg, s->sbm_maccfg);
-
+
+ SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
+ SBMAC_WRITECSR(s->sbm_maccfg,cfg);
+
return 1;
}
/**********************************************************************
* SBMAC_SET_DUPLEX(s,duplex,fc)
- *
+ *
* Set Ethernet duplex and flow control options for this MAC
* Warning: must be called when MAC is off!
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* duplex - duplex setting (see sbmac_duplex_t)
* fc - flow control setting (see sbmac_fc_t)
- *
+ *
* Return value:
* 1 if ok
* 0 if an invalid parameter combination was specified
@@ -1938,67 +1965,67 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc)
{
uint64_t cfg;
-
+
/*
* Save new current values
*/
-
+
s->sbm_duplex = duplex;
s->sbm_fc = fc;
-
+
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
-
+
/*
- * Read current register values
+ * Read current register values
*/
-
- cfg = __raw_readq(s->sbm_maccfg);
-
+
+ cfg = SBMAC_READCSR(s->sbm_maccfg);
+
/*
* Mask off the stuff we're about to change
*/
-
+
cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
-
-
+
+
switch (duplex) {
case sbmac_duplex_half:
switch (fc) {
case sbmac_fc_disabled:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
break;
-
+
case sbmac_fc_collision:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
break;
-
+
case sbmac_fc_carrier:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
break;
-
+
case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
+ /* fall through */
case sbmac_fc_frame: /* not valid in half duplex */
default: /* invalid selection */
return 0;
}
break;
-
+
case sbmac_duplex_full:
switch (fc) {
case sbmac_fc_disabled:
cfg |= V_MAC_FC_CMD_DISABLED;
break;
-
+
case sbmac_fc_frame:
cfg |= V_MAC_FC_CMD_ENABLED;
break;
-
+
case sbmac_fc_collision: /* not valid in full duplex */
case sbmac_fc_carrier: /* not valid in full duplex */
case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
+ /* fall through */
default:
return 0;
}
@@ -2007,13 +2034,13 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
/* XXX not implemented */
break;
}
-
+
/*
- * Send the bits back to the hardware
+ * Send the bits back to the hardware
*/
-
- __raw_writeq(cfg, s->sbm_maccfg);
-
+
+ SBMAC_WRITECSR(s->sbm_maccfg,cfg);
+
return 1;
}
@@ -2022,12 +2049,12 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
/**********************************************************************
* SBMAC_INTR()
- *
+ *
* Interrupt handler for MAC interrupts
- *
- * Input parameters:
+ *
+ * Input parameters:
* MAC structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -2039,27 +2066,27 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
int handled = 0;
for (;;) {
-
+
/*
* Read the ISR (this clears the bits in the real
* register, except for counter addr)
*/
-
- isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
-
+
+ isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
+
if (isr == 0)
break;
handled = 1;
-
+
/*
* Transmits on channel 0
*/
-
+
if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
sbdma_tx_process(sc,&(sc->sbm_txdma));
}
-
+
/*
* Receives on channel 0
*/
@@ -2079,8 +2106,8 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
* EOP_SEEN here takes care of this case.
* (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
*/
-
-
+
+
if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
sbdma_rx_process(sc,&(sc->sbm_rxdma));
}
@@ -2091,29 +2118,29 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
/**********************************************************************
* SBMAC_START_TX(skb,dev)
- *
- * Start output on the specified interface. Basically, we
+ *
+ * Start output on the specified interface. Basically, we
* queue as many buffers as we can until the ring fills up, or
* we run off the end of the queue, whichever comes first.
- *
- * Input parameters:
- *
- *
+ *
+ * Input parameters:
+ *
+ *
* Return value:
* nothing
********************************************************************* */
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
/* lock eth irq */
spin_lock_irq (&sc->sbm_lock);
-
+
/*
- * Put the buffer on the transmit ring. If we
+ * Put the buffer on the transmit ring. If we
* don't have room, stop the queue.
*/
-
+
if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
/* XXX save skb that we could not send */
netif_stop_queue(dev);
@@ -2121,24 +2148,24 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
return 1;
}
-
+
dev->trans_start = jiffies;
-
+
spin_unlock_irq (&sc->sbm_lock);
-
+
return 0;
}
/**********************************************************************
* SBMAC_SETMULTI(sc)
- *
+ *
* Reprogram the multicast table into the hardware, given
* the list of multicasts associated with the interface
* structure.
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -2146,75 +2173,75 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
static void sbmac_setmulti(struct sbmac_softc *sc)
{
uint64_t reg;
- volatile void __iomem *port;
+ sbmac_port_t port;
int idx;
struct dev_mc_list *mclist;
struct net_device *dev = sc->sbm_dev;
-
- /*
+
+ /*
* Clear out entire multicast table. We do this by nuking
* the entire hash table and all the direct matches except
- * the first one, which is used for our station address
+ * the first one, which is used for our station address
*/
-
+
for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
}
-
+
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
- __raw_writeq(0, port);
+ SBMAC_WRITECSR(port,0);
}
-
+
/*
* Clear the filter to say we don't want any multicasts.
*/
-
- reg = __raw_readq(sc->sbm_rxfilter);
+
+ reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
- __raw_writeq(reg, sc->sbm_rxfilter);
-
+ SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+
if (dev->flags & IFF_ALLMULTI) {
- /*
- * Enable ALL multicasts. Do this by inverting the
- * multicast enable bit.
+ /*
+ * Enable ALL multicasts. Do this by inverting the
+ * multicast enable bit.
*/
- reg = __raw_readq(sc->sbm_rxfilter);
+ reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
- __raw_writeq(reg, sc->sbm_rxfilter);
+ SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
return;
}
+
-
- /*
+ /*
* Progam new multicast entries. For now, only use the
* perfect filter. In the future we'll need to use the
* hash filter if the perfect filter overflows
*/
-
+
/* XXX only using perfect filter for now, need to use hash
* XXX if the table overflows */
-
+
idx = 1; /* skip station address */
mclist = dev->mc_list;
while (mclist && (idx < MAC_ADDR_COUNT)) {
reg = sbmac_addr2reg(mclist->dmi_addr);
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
- __raw_writeq(reg, port);
+ SBMAC_WRITECSR(port,reg);
idx++;
mclist = mclist->next;
}
-
- /*
+
+ /*
* Enable the "accept multicast bits" if we programmed at least one
- * multicast.
+ * multicast.
*/
-
+
if (idx > 1) {
- reg = __raw_readq(sc->sbm_rxfilter);
+ reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg |= M_MAC_MCAST_EN;
- __raw_writeq(reg, sc->sbm_rxfilter);
+ SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
}
}
@@ -2223,12 +2250,12 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
/**********************************************************************
* SBMAC_PARSE_XDIGIT(str)
- *
+ *
* Parse a hex digit, returning its value
- *
- * Input parameters:
+ *
+ * Input parameters:
* str - character
- *
+ *
* Return value:
* hex value, or -1 if invalid
********************************************************************* */
@@ -2236,7 +2263,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
static int sbmac_parse_xdigit(char str)
{
int digit;
-
+
if ((str >= '0') && (str <= '9'))
digit = str - '0';
else if ((str >= 'a') && (str <= 'f'))
@@ -2245,20 +2272,20 @@ static int sbmac_parse_xdigit(char str)
digit = str - 'A' + 10;
else
return -1;
-
+
return digit;
}
/**********************************************************************
* SBMAC_PARSE_HWADDR(str,hwaddr)
- *
+ *
* Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
* Ethernet address.
- *
- * Input parameters:
+ *
+ * Input parameters:
* str - string
* hwaddr - pointer to hardware address
- *
+ *
* Return value:
* 0 if ok, else -1
********************************************************************* */
@@ -2267,7 +2294,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
{
int digit1,digit2;
int idx = 6;
-
+
while (*str && (idx > 0)) {
digit1 = sbmac_parse_xdigit(*str);
if (digit1 < 0)
@@ -2275,7 +2302,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
str++;
if (!*str)
return -1;
-
+
if ((*str == ':') || (*str == '-')) {
digit2 = digit1;
digit1 = 0;
@@ -2286,10 +2313,10 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
return -1;
str++;
}
-
+
*hwaddr++ = (digit1 << 4) | digit2;
idx--;
-
+
if (*str == '-')
str++;
if (*str == ':')
@@ -2310,12 +2337,12 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
/**********************************************************************
* SBMAC_INIT(dev)
- *
+ *
* Attach routine - init hardware and hook ourselves into linux
- *
- * Input parameters:
+ *
+ * Input parameters:
* dev - net_device structure
- *
+ *
* Return value:
* status
********************************************************************* */
@@ -2327,53 +2354,53 @@ static int sbmac_init(struct net_device *dev, int idx)
uint64_t ea_reg;
int i;
int err;
-
+
sc = netdev_priv(dev);
-
+
/* Determine controller base address */
-
+
sc->sbm_base = IOADDR(dev->base_addr);
sc->sbm_dev = dev;
sc->sbe_idx = idx;
-
+
eaddr = sc->sbm_hwaddr;
-
- /*
+
+ /*
* Read the ethernet address. The firwmare left this programmed
* for us in the ethernet address register for each mac.
*/
-
- ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
- __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
+
+ ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
+ SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
for (i = 0; i < 6; i++) {
eaddr[i] = (uint8_t) (ea_reg & 0xFF);
ea_reg >>= 8;
}
-
+
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = eaddr[i];
}
-
-
+
+
/*
- * Init packet size
+ * Init packet size
*/
-
+
sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
- /*
+ /*
* Initialize context (get pointers to registers and stuff), then
* allocate the memory for the descriptor tables.
*/
-
+
sbmac_initctx(sc);
-
+
/*
* Set up Linux device callins
*/
-
+
spin_lock_init(&(sc->sbm_lock));
-
+
dev->open = sbmac_open;
dev->hard_start_xmit = sbmac_start_tx;
dev->stop = sbmac_close;
@@ -2392,7 +2419,7 @@ static int sbmac_init(struct net_device *dev, int idx)
if (err)
goto out_uninit;
- if (sc->rx_hw_checksum == ENABLE) {
+ if (periph_rev >= 2) {
printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
sc->sbm_dev->name);
}
@@ -2403,10 +2430,10 @@ static int sbmac_init(struct net_device *dev, int idx)
* was being displayed)
*/
printk(KERN_INFO
- "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
dev->name, dev->base_addr,
eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
-
+
return 0;
@@ -2420,86 +2447,54 @@ static int sbmac_init(struct net_device *dev, int idx)
static int sbmac_open(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
if (debug > 1) {
printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
}
-
- /*
+
+ /*
* map/route interrupt (clear status first, in case something
* weird is pending; we haven't initialized the mac registers
* yet)
*/
- __raw_readq(sc->sbm_isr);
+ SBMAC_READCSR(sc->sbm_isr);
if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev))
return -EBUSY;
/*
- * Probe phy address
- */
-
- if(sbmac_mii_probe(dev) == -1) {
- printk("%s: failed to probe PHY.\n", dev->name);
- return -EINVAL;
- }
-
- /*
- * Configure default speed
+ * Configure default speed
*/
sbmac_mii_poll(sc,noisy_mii);
-
+
/*
* Turn on the channel
*/
sbmac_set_channel_state(sc,sbmac_state_on);
-
+
/*
* XXX Station address is in dev->dev_addr
*/
-
+
if (dev->if_port == 0)
- dev->if_port = 0;
-
+ dev->if_port = 0;
+
netif_start_queue(dev);
-
+
sbmac_set_rx_mode(dev);
-
+
/* Set the timer to check for link beat. */
init_timer(&sc->sbm_timer);
sc->sbm_timer.expires = jiffies + 2 * HZ/100;
sc->sbm_timer.data = (unsigned long)dev;
sc->sbm_timer.function = &sbmac_timer;
add_timer(&sc->sbm_timer);
-
+
return 0;
}
-static int sbmac_mii_probe(struct net_device *dev)
-{
- int i;
- struct sbmac_softc *s = netdev_priv(dev);
- u16 bmsr, id1, id2;
- u32 vendor, device;
-
- for (i=1; i<31; i++) {
- bmsr = sbmac_mii_read(s, i, MII_BMSR);
- if (bmsr != 0) {
- s->sbm_phys[0] = i;
- id1 = sbmac_mii_read(s, i, MII_PHYIDR1);
- id2 = sbmac_mii_read(s, i, MII_PHYIDR2);
- vendor = ((u32)id1 << 6) | ((id2 >> 10) & 0x3f);
- device = (id2 >> 4) & 0x3f;
-
- printk(KERN_INFO "%s: found phy %d, vendor %06x part %02x\n",
- dev->name, i, vendor, device);
- return i;
- }
- }
- return -1;
-}
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
@@ -2614,20 +2609,20 @@ static void sbmac_timer(unsigned long data)
int mii_status;
spin_lock_irq (&sc->sbm_lock);
-
+
/* make IFF_RUNNING follow the MII status bit "Link established" */
mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
-
+
if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
if (mii_status & BMSR_LINKSTAT) {
netif_carrier_on(dev);
}
else {
- netif_carrier_off(dev);
+ netif_carrier_off(dev);
}
}
-
+
/*
* Poll the PHY to see what speed we should be running at
*/
@@ -2645,9 +2640,9 @@ static void sbmac_timer(unsigned long data)
sbmac_channel_start(sc);
}
}
-
+
spin_unlock_irq (&sc->sbm_lock);
-
+
sc->sbm_timer.expires = jiffies + next_tick;
add_timer(&sc->sbm_timer);
}
@@ -2656,13 +2651,13 @@ static void sbmac_timer(unsigned long data)
static void sbmac_tx_timeout (struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
spin_lock_irq (&sc->sbm_lock);
-
-
+
+
dev->trans_start = jiffies;
sc->sbm_stats.tx_errors++;
-
+
spin_unlock_irq (&sc->sbm_lock);
printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
@@ -2675,13 +2670,13 @@ static struct net_device_stats *sbmac_get_stats(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
unsigned long flags;
-
+
spin_lock_irqsave(&sc->sbm_lock, flags);
-
+
/* XXX update other stats here */
-
+
spin_unlock_irqrestore(&sc->sbm_lock, flags);
-
+
return &sc->sbm_stats;
}
@@ -2698,8 +2693,8 @@ static void sbmac_set_rx_mode(struct net_device *dev)
/*
* Promiscuous changed.
*/
-
- if (dev->flags & IFF_PROMISC) {
+
+ if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
msg_flag = 1;
sbmac_promiscuous_mode(sc,1);
@@ -2710,18 +2705,18 @@ static void sbmac_set_rx_mode(struct net_device *dev)
}
}
spin_unlock_irqrestore(&sc->sbm_lock, flags);
-
+
if (msg_flag) {
printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
dev->name,(msg_flag==1)?"en":"dis");
}
-
+
/*
* Program the multicasts. Do this every time.
*/
-
+
sbmac_setmulti(sc);
-
+
}
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2730,10 +2725,10 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
u16 *data = (u16 *)&rq->ifr_ifru;
unsigned long flags;
int retval;
-
+
spin_lock_irqsave(&sc->sbm_lock, flags);
retval = 0;
-
+
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = sc->sbm_phys[0] & 0x1f;
@@ -2755,7 +2750,7 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
default:
retval = -EOPNOTSUPP;
}
-
+
spin_unlock_irqrestore(&sc->sbm_lock, flags);
return retval;
}
@@ -2786,7 +2781,7 @@ static int sbmac_close(struct net_device *dev)
sbdma_emptyring(&(sc->sbm_txdma));
sbdma_emptyring(&(sc->sbm_rxdma));
-
+
return 0;
}
@@ -2798,13 +2793,13 @@ sbmac_setup_hwaddr(int chan,char *addr)
{
uint8_t eaddr[6];
uint64_t val;
- unsigned long port;
+ sbmac_port_t port;
port = A_MAC_CHANNEL_BASE(chan);
sbmac_parse_hwaddr(addr,eaddr);
val = sbmac_addr2reg(eaddr);
- __raw_writeq(val, IOADDR(port+R_MAC_ETHERNET_ADDR));
- val = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),val);
+ val = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
}
#endif
@@ -2815,9 +2810,9 @@ sbmac_init_module(void)
{
int idx;
struct net_device *dev;
- unsigned long port;
+ sbmac_port_t port;
int chip_max_units;
-
+
/*
* For bringup when not using the firmware, we can pre-fill
* the MAC addresses using the environment variables
@@ -2863,13 +2858,13 @@ sbmac_init_module(void)
port = A_MAC_CHANNEL_BASE(idx);
- /*
+ /*
* The R_MAC_ETHERNET_ADDR register will be set to some nonzero
* value for us by the firmware if we're going to use this MAC.
* If we find a zero, skip this MAC.
*/
- sbmac_orig_hwaddr[idx] = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ sbmac_orig_hwaddr[idx] = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
if (sbmac_orig_hwaddr[idx] == 0) {
printk(KERN_DEBUG "sbmac: not configuring MAC at "
"%lx\n", port);
@@ -2881,7 +2876,7 @@ sbmac_init_module(void)
*/
dev = alloc_etherdev(sizeof(struct sbmac_softc));
- if (!dev)
+ if (!dev)
return -ENOMEM; /* return ENOMEM */
printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
@@ -2891,7 +2886,8 @@ sbmac_init_module(void)
dev->mem_end = 0;
if (sbmac_init(dev, idx)) {
port = A_MAC_CHANNEL_BASE(idx);
- __raw_writeq(sbmac_orig_hwaddr[idx], IOADDR(port+R_MAC_ETHERNET_ADDR));
+ SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
+ sbmac_orig_hwaddr[idx]);
free_netdev(dev);
continue;
}
diff --git a/trunk/drivers/net/sgiseeq.c b/trunk/drivers/net/sgiseeq.c
index a4614df38a90..9bc3b1c0dd6a 100644
--- a/trunk/drivers/net/sgiseeq.c
+++ b/trunk/drivers/net/sgiseeq.c
@@ -32,6 +32,8 @@
#include "sgiseeq.h"
+static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
+
static char *sgiseeqstr = "SGI Seeq8003";
/*
@@ -111,9 +113,9 @@ static struct net_device *root_sgiseeq_dev;
static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
{
- hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
+ hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
udelay(20);
- hregs->reset = 0;
+ hregs->rx_reset = 0;
}
static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
@@ -250,6 +252,7 @@ void sgiseeq_dump_rings(void)
#define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
#define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
+#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
struct sgiseeq_regs *sregs)
@@ -271,6 +274,8 @@ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
sregs->tstat = TSTAT_INIT_SEEQ;
}
+ hregs->rx_dconfig |= RDMACFG_INIT;
+
hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
@@ -441,7 +446,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
spin_lock(&sp->tx_lock);
/* Ack the IRQ and set software state. */
- hregs->reset = HPC3_ERST_CLRIRQ;
+ hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
/* Always check for received packets. */
sgiseeq_rx(dev, sp, hregs, sregs);
@@ -488,13 +493,11 @@ static int sgiseeq_close(struct net_device *dev)
{
struct sgiseeq_private *sp = netdev_priv(dev);
struct sgiseeq_regs *sregs = sp->sregs;
- unsigned int irq = dev->irq;
netif_stop_queue(dev);
/* Shutdown the Seeq. */
reset_hpc3_and_seeq(sp->hregs, sregs);
- free_irq(irq, dev);
return 0;
}
@@ -641,7 +644,7 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
-static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
+static int sgiseeq_init(struct hpc3_regs* regs, int irq)
{
struct sgiseeq_init_block *sr;
struct sgiseeq_private *sp;
@@ -677,8 +680,8 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
gpriv = sp;
gdev = dev;
#endif
- sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
- sp->hregs = &hpcregs->ethregs;
+ sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
+ sp->hregs = &hpc3c0->ethregs;
sp->name = sgiseeqstr;
sp->mode = SEEQ_RCMD_RBCAST;
@@ -695,11 +698,6 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
- /* Setup PIO and DMA transfer timing */
- sp->hregs->pconfig = 0x161;
- sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
- HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
-
/* Reset the chip. */
hpc3_eth_reset(sp->hregs);
@@ -726,7 +724,7 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
goto err_out_free_page;
}
- printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
+ printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
@@ -736,7 +734,7 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
return 0;
err_out_free_page:
- free_page((unsigned long) sp->srings);
+ free_page((unsigned long) sp);
err_out_free_dev:
kfree(dev);
@@ -746,6 +744,8 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
static int __init sgiseeq_probe(void)
{
+ printk(version);
+
/* On board adapter on 1st HPC is always present */
return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
}
@@ -754,12 +754,15 @@ static void __exit sgiseeq_exit(void)
{
struct net_device *next, *dev;
struct sgiseeq_private *sp;
+ int irq;
for (dev = root_sgiseeq_dev; dev; dev = next) {
sp = (struct sgiseeq_private *) netdev_priv(dev);
next = sp->next_module;
+ irq = dev->irq;
unregister_netdev(dev);
- free_page((unsigned long) sp->srings);
+ free_irq(irq, dev);
+ free_page((unsigned long) sp);
free_netdev(dev);
}
}
@@ -767,6 +770,4 @@ static void __exit sgiseeq_exit(void)
module_init(sgiseeq_probe);
module_exit(sgiseeq_exit);
-MODULE_DESCRIPTION("SGI Seeq 8003 driver");
-MODULE_AUTHOR("Linux/MIPS Mailing List ");
MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c
index 572f121b1f4e..c2e6484ef138 100644
--- a/trunk/drivers/net/skge.c
+++ b/trunk/drivers/net/skge.c
@@ -730,7 +730,6 @@ static struct ethtool_ops skge_ethtool_ops = {
.phys_id = skge_phys_id,
.get_stats_count = skge_get_stats_count,
.get_ethtool_stats = skge_get_ethtool_stats,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
/*
@@ -3097,7 +3096,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
/* read the mac address */
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* device is off until link detection */
netif_carrier_off(dev);
diff --git a/trunk/drivers/net/sunbmac.c b/trunk/drivers/net/sunbmac.c
index cfaf47c63c58..f88f5e32b714 100644
--- a/trunk/drivers/net/sunbmac.c
+++ b/trunk/drivers/net/sunbmac.c
@@ -214,8 +214,7 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
{
struct bmac_init_block *bb = bp->bmac_block;
struct net_device *dev = bp->dev;
- int i;
- gfp_t gfp_flags = GFP_KERNEL;
+ int i, gfp_flags = GFP_KERNEL;
if (from_irq || in_interrupt())
gfp_flags = GFP_ATOMIC;
diff --git a/trunk/drivers/net/sunbmac.h b/trunk/drivers/net/sunbmac.h
index b0dbc5187143..5674003fc38a 100644
--- a/trunk/drivers/net/sunbmac.h
+++ b/trunk/drivers/net/sunbmac.h
@@ -339,7 +339,7 @@ struct bigmac {
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, gfp_t gfp_flags)
+static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, int gfp_flags)
{
struct sk_buff *skb;
diff --git a/trunk/drivers/net/sundance.c b/trunk/drivers/net/sundance.c
index 5de0554fd7c6..d500a5771dbc 100644
--- a/trunk/drivers/net/sundance.c
+++ b/trunk/drivers/net/sundance.c
@@ -518,7 +518,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
#else
int bar = 1;
#endif
- int phy, phy_idx = 0;
/* when built into the kernel, we only print version if device is found */
@@ -550,7 +549,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] =
le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->base_addr = (unsigned long)ioaddr;
dev->irq = irq;
@@ -607,30 +605,32 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
- np->phys[0] = 1; /* Default setting */
- np->mii_preamble_required++;
- for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
- int mii_status = mdio_read(dev, phy, MII_BMSR);
- int phyx = phy & 0x1f;
- if (mii_status != 0xffff && mii_status != 0x0000) {
- np->phys[phy_idx++] = phyx;
- np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
- if ((mii_status & 0x0040) == 0)
- np->mii_preamble_required++;
- printk(KERN_INFO "%s: MII PHY found at address %d, status "
- "0x%4.4x advertising %4.4x.\n",
- dev->name, phyx, mii_status, np->mii_if.advertising);
+ if (1) {
+ int phy, phy_idx = 0;
+ np->phys[0] = 1; /* Default setting */
+ np->mii_preamble_required++;
+ for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
+ int mii_status = mdio_read(dev, phy, MII_BMSR);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ np->phys[phy_idx++] = phy;
+ np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
+ if ((mii_status & 0x0040) == 0)
+ np->mii_preamble_required++;
+ printk(KERN_INFO "%s: MII PHY found at address %d, status "
+ "0x%4.4x advertising %4.4x.\n",
+ dev->name, phy, mii_status, np->mii_if.advertising);
+ }
}
- }
- np->mii_preamble_required--;
+ np->mii_preamble_required--;
- if (phy_idx == 0) {
- printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
- dev->name, ioread32(ioaddr + ASICCtrl));
- goto err_out_unregister;
- }
+ if (phy_idx == 0) {
+ printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
+ dev->name, ioread32(ioaddr + ASICCtrl));
+ goto err_out_unregister;
+ }
- np->mii_if.phy_id = np->phys[0];
+ np->mii_if.phy_id = np->phys[0];
+ }
/* Parse override configuration */
np->an_enable = 1;
@@ -692,7 +692,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
/* Reset the chip to erase previous misconfiguration. */
if (netif_msg_hw(np))
printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
- iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
+ iowrite16(0x007f, ioaddr + ASICCtrl + 2);
if (netif_msg_hw(np))
printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
@@ -1619,7 +1619,6 @@ static struct ethtool_ops ethtool_ops = {
.get_link = get_link,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/trunk/drivers/net/tokenring/ibmtr.c b/trunk/drivers/net/tokenring/ibmtr.c
index 9f491563944e..32057e65808b 100644
--- a/trunk/drivers/net/tokenring/ibmtr.c
+++ b/trunk/drivers/net/tokenring/ibmtr.c
@@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct net_device *dev)
if (dev->base_addr) {
outb(0,dev->base_addr+ADAPTRESET);
- schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
+ schedule_timeout(TR_RST_TIME); /* wait 50ms */
outb(0,dev->base_addr+ADAPTRESETREL);
}
@@ -854,7 +854,8 @@ static int tok_init_card(struct net_device *dev)
writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
outb(0, PIOaddr + ADAPTRESET);
- schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
+ current->state=TASK_UNINTERRUPTIBLE;
+ schedule_timeout(TR_RST_TIME); /* wait 50ms */
outb(0, PIOaddr + ADAPTRESETREL);
#ifdef ENABLE_PAGING
@@ -902,8 +903,8 @@ static int tok_open(struct net_device *dev)
DPRINTK("Adapter is up and running\n");
return 0;
}
- i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
- /* wait 30 seconds */
+ current->state=TASK_INTERRUPTIBLE;
+ i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
}
outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
diff --git a/trunk/drivers/net/tokenring/olympic.c b/trunk/drivers/net/tokenring/olympic.c
index 05477d24fd49..9e7923192a49 100644
--- a/trunk/drivers/net/tokenring/olympic.c
+++ b/trunk/drivers/net/tokenring/olympic.c
@@ -1101,7 +1101,7 @@ static int olympic_close(struct net_device *dev)
while(olympic_priv->srb_queued) {
- t = schedule_timeout_interruptible(60*HZ);
+ t = schedule_timeout(60*HZ);
if(signal_pending(current)) {
printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
diff --git a/trunk/drivers/net/tokenring/tms380tr.c b/trunk/drivers/net/tokenring/tms380tr.c
index c1925590a0e1..2e39bf1f7462 100644
--- a/trunk/drivers/net/tokenring/tms380tr.c
+++ b/trunk/drivers/net/tokenring/tms380tr.c
@@ -1243,7 +1243,8 @@ void tms380tr_wait(unsigned long time)
tmp = jiffies + time/(1000000/HZ);
do {
- tmp = schedule_timeout_interruptible(tmp);
+ current->state = TASK_INTERRUPTIBLE;
+ tmp = schedule_timeout(tmp);
} while(time_after(tmp, jiffies));
#else
udelay(time);
diff --git a/trunk/drivers/net/tulip/de2104x.c b/trunk/drivers/net/tulip/de2104x.c
index 6b8eee8f7bfd..a22d00198e4d 100644
--- a/trunk/drivers/net/tulip/de2104x.c
+++ b/trunk/drivers/net/tulip/de2104x.c
@@ -1787,15 +1787,10 @@ static void __init de21041_get_srom_info (struct de_private *de)
/* DEC now has a specification but early board makers
just put the address in the first EEPROM locations. */
/* This does memcmp(eedata, eedata+16, 8) */
-
-#ifndef CONFIG_MIPS_COBALT
-
for (i = 0; i < 8; i ++)
if (ee_data[i] != ee_data[16+i])
sa_offset = 20;
-#endif
-
/* store MAC address */
for (i = 0; i < 6; i ++)
de->dev->dev_addr[i] = ee_data[i + sa_offset];
diff --git a/trunk/drivers/net/typhoon.c b/trunk/drivers/net/typhoon.c
index 4c76cb794bfb..ecfa6f8805ce 100644
--- a/trunk/drivers/net/typhoon.c
+++ b/trunk/drivers/net/typhoon.c
@@ -419,9 +419,10 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
TYPHOON_STATUS_WAITING_FOR_HOST)
goto out;
- if(wait_type == WaitSleep)
- schedule_timeout_uninterruptible(1);
- else
+ if(wait_type == WaitSleep) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+ } else
udelay(TYPHOON_UDELAY);
}
diff --git a/trunk/drivers/net/via-rhine.c b/trunk/drivers/net/via-rhine.c
index 241871589283..fc7738ffbfff 100644
--- a/trunk/drivers/net/via-rhine.c
+++ b/trunk/drivers/net/via-rhine.c
@@ -490,8 +490,6 @@ struct rhine_private {
u8 tx_thresh, rx_thresh;
struct mii_if_info mii_if;
- struct work_struct tx_timeout_task;
- struct work_struct check_media_task;
void __iomem *base;
};
@@ -499,8 +497,6 @@ static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
static int rhine_open(struct net_device *dev);
static void rhine_tx_timeout(struct net_device *dev);
-static void rhine_tx_timeout_task(struct net_device *dev);
-static void rhine_check_media_task(struct net_device *dev);
static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static void rhine_tx(struct net_device *dev);
@@ -818,9 +814,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
for (i = 0; i < 6; i++)
dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->perm_addr)) {
+ if (!is_valid_ether_addr(dev->dev_addr)) {
rc = -EIO;
printk(KERN_ERR "Invalid MAC address\n");
goto err_out_unmap;
@@ -855,12 +850,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (rp->quirks & rqRhineI)
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
- INIT_WORK(&rp->tx_timeout_task,
- (void (*)(void *))rhine_tx_timeout_task, dev);
-
- INIT_WORK(&rp->check_media_task,
- (void (*)(void *))rhine_check_media_task, dev);
-
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev);
if (rc)
@@ -1087,11 +1076,6 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
ioaddr + ChipCmd1);
}
-static void rhine_check_media_task(struct net_device *dev)
-{
- rhine_check_media(dev, 0);
-}
-
static void init_registers(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -1145,8 +1129,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
if (quirks & rqRhineI) {
iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR
- /* Do not call from ISR! */
- msleep(1);
+ /* Can be called from ISR. Evil. */
+ mdelay(1);
/* 0x80 must be set immediately before turning it off */
iowrite8(0x80, ioaddr + MIICmd);
@@ -1234,16 +1218,6 @@ static int rhine_open(struct net_device *dev)
}
static void rhine_tx_timeout(struct net_device *dev)
-{
- struct rhine_private *rp = netdev_priv(dev);
-
- /*
- * Move bulk of work outside of interrupt context
- */
- schedule_work(&rp->tx_timeout_task);
-}
-
-static void rhine_tx_timeout_task(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
@@ -1651,7 +1625,7 @@ static void rhine_error(struct net_device *dev, int intr_status)
spin_lock(&rp->lock);
if (intr_status & IntrLinkChange)
- schedule_work(&rp->check_media_task);
+ rhine_check_media(dev, 0);
if (intr_status & IntrStatsMax) {
rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1855,7 +1829,6 @@ static struct ethtool_ops netdev_ethtool_ops = {
.set_wol = rhine_set_wol,
.get_sg = ethtool_op_get_sg,
.get_tx_csum = ethtool_op_get_tx_csum,
- .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1899,9 +1872,6 @@ static int rhine_close(struct net_device *dev)
spin_unlock_irq(&rp->lock);
free_irq(rp->pdev->irq, dev);
-
- flush_scheduled_work();
-
free_rbufs(dev);
free_tbufs(dev);
free_ring(dev);
diff --git a/trunk/drivers/net/wan/cosa.c b/trunk/drivers/net/wan/cosa.c
index ae9e897c255e..7ff814fd65d0 100644
--- a/trunk/drivers/net/wan/cosa.c
+++ b/trunk/drivers/net/wan/cosa.c
@@ -1617,7 +1617,8 @@ static int get_wait_data(struct cosa_data *cosa)
return r;
}
/* sleep if not ready to read */
- schedule_timeout_interruptible(1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
}
printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
@@ -1643,7 +1644,8 @@ static int put_wait_data(struct cosa_data *cosa, int data)
}
#if 0
/* sleep if not ready to read */
- schedule_timeout_interruptible(1);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
#endif
}
printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
diff --git a/trunk/drivers/net/wan/cycx_drv.c b/trunk/drivers/net/wan/cycx_drv.c
index e6d005726aad..9e56fc346ba4 100644
--- a/trunk/drivers/net/wan/cycx_drv.c
+++ b/trunk/drivers/net/wan/cycx_drv.c
@@ -109,7 +109,7 @@ static long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
* < 0 error.
* Context: process */
-static int __init cycx_drv_init(void)
+int __init cycx_drv_init(void)
{
printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
copyright);
@@ -119,7 +119,7 @@ static int __init cycx_drv_init(void)
/* Module 'remove' entry point.
* o release all remaining system resources */
-static void cycx_drv_cleanup(void)
+void cycx_drv_cleanup(void)
{
}
@@ -184,7 +184,8 @@ int cycx_down(struct cycx_hw *hw)
}
/* Enable interrupt generation. */
-static void cycx_inten(struct cycx_hw *hw)
+EXPORT_SYMBOL(cycx_inten);
+void cycx_inten(struct cycx_hw *hw)
{
writeb(0, hw->dpmbase);
}
diff --git a/trunk/drivers/net/wan/cycx_main.c b/trunk/drivers/net/wan/cycx_main.c
index 430b1f630fb4..7b48064364dc 100644
--- a/trunk/drivers/net/wan/cycx_main.c
+++ b/trunk/drivers/net/wan/cycx_main.c
@@ -103,7 +103,7 @@ static struct cycx_device *cycx_card_array; /* adapter data space */
* < 0 error.
* Context: process
*/
-static int __init cycx_init(void)
+int __init cycx_init(void)
{
int cnt, err = -ENOMEM;
diff --git a/trunk/drivers/net/wan/cycx_x25.c b/trunk/drivers/net/wan/cycx_x25.c
index a631d1c2fa14..02d57c0b4243 100644
--- a/trunk/drivers/net/wan/cycx_x25.c
+++ b/trunk/drivers/net/wan/cycx_x25.c
@@ -78,7 +78,6 @@
#define CYCLOMX_X25_DEBUG 1
-#include /* isdigit() */
#include /* return codes */
#include /* ARPHRD_HWX25 */
#include /* printk(), and other useful stuff */
@@ -419,7 +418,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
/* Set channel timeouts (default if not specified) */
chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
- } else if (isdigit(conf->addr[0])) { /* PVC */
+ } else if (is_digit(conf->addr[0])) { /* PVC */
s16 lcn = dec_to_uint(conf->addr, 0);
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
@@ -1532,7 +1531,7 @@ static unsigned dec_to_uint(u8 *str, int len)
if (!len)
len = strlen(str);
- for (; len && isdigit(*str); ++str, --len)
+ for (; len && is_digit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned) '0');
return val;
diff --git a/trunk/drivers/net/wan/dscc4.c b/trunk/drivers/net/wan/dscc4.c
index 2f61a47b4716..520a77a798e2 100644
--- a/trunk/drivers/net/wan/dscc4.c
+++ b/trunk/drivers/net/wan/dscc4.c
@@ -446,8 +446,8 @@ static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv,
return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda;
}
-static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
- struct net_device *dev, const char *msg)
+int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
+ const char *msg)
{
int ret = 0;
@@ -466,9 +466,8 @@ static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
return ret;
}
-static void dscc4_tx_print(struct net_device *dev,
- struct dscc4_dev_priv *dpriv,
- char *msg)
+void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
+ char *msg)
{
printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
@@ -508,8 +507,7 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv)
}
}
-static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
- struct net_device *dev)
+inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
{
unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
struct RxFD *rx_fd = dpriv->rx_fd + dirty;
@@ -544,7 +542,8 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
msg, i);
goto done;
}
- schedule_timeout_uninterruptible(10);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
rmb();
} while (++i > 0);
printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
@@ -589,7 +588,8 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv)
(dpriv->iqtx[cur] & Xpr))
break;
smp_rmb();
- schedule_timeout_uninterruptible(10);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
} while (++i > 0);
return (i >= 0 ) ? i : -EAGAIN;
@@ -1035,7 +1035,8 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
/* Flush posted writes */
readl(ioaddr + GSTAR);
- schedule_timeout_uninterruptible(10);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
for (i = 0; i < 16; i++)
pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
@@ -1893,7 +1894,7 @@ static void dscc4_rx_irq(struct dscc4_pci_priv *priv,
* It failed and locked solid. Thus the introduction of a dummy skb.
* Problem is acknowledged in errata sheet DS5. Joy :o/
*/
-static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
+struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
{
struct sk_buff *skb;
diff --git a/trunk/drivers/net/wan/farsync.c b/trunk/drivers/net/wan/farsync.c
index 7981a2c7906e..2c83cca34b86 100644
--- a/trunk/drivers/net/wan/farsync.c
+++ b/trunk/drivers/net/wan/farsync.c
@@ -74,11 +74,11 @@ MODULE_LICENSE("GPL");
/*
* Modules parameters and associated varaibles
*/
-static int fst_txq_low = FST_LOW_WATER_MARK;
-static int fst_txq_high = FST_HIGH_WATER_MARK;
-static int fst_max_reads = 7;
-static int fst_excluded_cards = 0;
-static int fst_excluded_list[FST_MAX_CARDS];
+int fst_txq_low = FST_LOW_WATER_MARK;
+int fst_txq_high = FST_HIGH_WATER_MARK;
+int fst_max_reads = 7;
+int fst_excluded_cards = 0;
+int fst_excluded_list[FST_MAX_CARDS];
module_param(fst_txq_low, int, 0);
module_param(fst_txq_high, int, 0);
@@ -572,13 +572,13 @@ static void do_bottom_half_rx(struct fst_card_info *card);
static void fst_process_tx_work_q(unsigned long work_q);
static void fst_process_int_work_q(unsigned long work_q);
-static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
-static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
+DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
-static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
-static spinlock_t fst_work_q_lock;
-static u64 fst_work_txq;
-static u64 fst_work_intq;
+struct fst_card_info *fst_card_array[FST_MAX_CARDS];
+spinlock_t fst_work_q_lock;
+u64 fst_work_txq;
+u64 fst_work_intq;
static void
fst_q_work_item(u64 * queue, int card_index)
@@ -980,7 +980,8 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
/* Wait for any previous command to complete */
while (mbval > NAK) {
spin_unlock_irqrestore(&card->card_lock, flags);
- schedule_timeout_uninterruptible(1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
spin_lock_irqsave(&card->card_lock, flags);
if (++safety > 2000) {
@@ -1497,7 +1498,7 @@ do_bottom_half_rx(struct fst_card_info *card)
* The interrupt service routine
* Dev_id is our fst_card_info pointer
*/
-static irqreturn_t
+irqreturn_t
fst_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct fst_card_info *card;
diff --git a/trunk/drivers/net/wan/hdlc_fr.c b/trunk/drivers/net/wan/hdlc_fr.c
index e1601d35dced..a5d6891c9d4c 100644
--- a/trunk/drivers/net/wan/hdlc_fr.c
+++ b/trunk/drivers/net/wan/hdlc_fr.c
@@ -330,7 +330,7 @@ static int pvc_close(struct net_device *dev)
-static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
pvc_device *pvc = dev_to_pvc(dev);
fr_proto_pvc_info info;
diff --git a/trunk/drivers/net/wan/lmc/lmc_debug.c b/trunk/drivers/net/wan/lmc/lmc_debug.c
index 3b94352b0d03..9dccd9546a17 100644
--- a/trunk/drivers/net/wan/lmc/lmc_debug.c
+++ b/trunk/drivers/net/wan/lmc/lmc_debug.c
@@ -8,10 +8,10 @@
/*
* Prints out len, max to 80 octets using printk, 20 per line
*/
-#ifdef DEBUG
-#ifdef LMC_PACKET_LOG
void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
{
+#ifdef DEBUG
+#ifdef LMC_PACKET_LOG
int iNewLine = 1;
char str[80], *pstr;
@@ -43,24 +43,26 @@ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
}
sprintf(pstr, "\n");
printk(str);
-}
#endif
#endif
+}
#ifdef DEBUG
u_int32_t lmcEventLogIndex = 0;
u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
+#endif
void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
{
+#ifdef DEBUG
lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
lmcEventLogBuf[lmcEventLogIndex++] = arg2;
lmcEventLogBuf[lmcEventLogIndex++] = arg3;
lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
+#endif
}
-#endif /* DEBUG */
void lmc_trace(struct net_device *dev, char *msg){
#ifdef LMC_TRACE
diff --git a/trunk/drivers/net/wan/lmc/lmc_media.c b/trunk/drivers/net/wan/lmc/lmc_media.c
index af8b55fdd9d9..f55ce76b00ed 100644
--- a/trunk/drivers/net/wan/lmc/lmc_media.c
+++ b/trunk/drivers/net/wan/lmc/lmc_media.c
@@ -47,6 +47,14 @@
* of the GNU General Public License version 2, incorporated herein by reference.
*/
+/*
+ * For lack of a better place, put the SSI cable stuff here.
+ */
+char *lmc_t1_cables[] = {
+ "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
+ "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
+};
+
/*
* protocol independent method.
*/
diff --git a/trunk/drivers/net/wan/pc300.h b/trunk/drivers/net/wan/pc300.h
index 2024b26b99e6..73401b0f0151 100644
--- a/trunk/drivers/net/wan/pc300.h
+++ b/trunk/drivers/net/wan/pc300.h
@@ -472,8 +472,24 @@ enum pc300_loopback_cmds {
#ifdef __KERNEL__
/* Function Prototypes */
+int dma_buf_write(pc300_t *, int, ucchar *, int);
+int dma_buf_read(pc300_t *, int, struct sk_buff *);
void tx_dma_start(pc300_t *, int);
+void rx_dma_start(pc300_t *, int);
+void tx_dma_stop(pc300_t *, int);
+void rx_dma_stop(pc300_t *, int);
+int cpc_queue_xmit(struct sk_buff *, struct net_device *);
+void cpc_net_rx(struct net_device *);
+void cpc_sca_status(pc300_t *, int);
+int cpc_change_mtu(struct net_device *, int);
+int cpc_ioctl(struct net_device *, struct ifreq *, int);
+int ch_config(pc300dev_t *);
+int rx_config(pc300dev_t *);
+int tx_config(pc300dev_t *);
+void cpc_opench(pc300dev_t *);
+void cpc_closech(pc300dev_t *);
int cpc_open(struct net_device *dev);
+int cpc_close(struct net_device *dev);
int cpc_set_media(hdlc_device *, int);
#endif /* __KERNEL__ */
diff --git a/trunk/drivers/net/wan/pc300_drv.c b/trunk/drivers/net/wan/pc300_drv.c
index a3e65d1bc19b..3e7753b10717 100644
--- a/trunk/drivers/net/wan/pc300_drv.c
+++ b/trunk/drivers/net/wan/pc300_drv.c
@@ -291,7 +291,6 @@ static uclong detect_ram(pc300_t *);
static void plx_init(pc300_t *);
static void cpc_trace(struct net_device *, struct sk_buff *, char);
static int cpc_attach(struct net_device *, unsigned short, unsigned short);
-static int cpc_close(struct net_device *dev);
#ifdef CONFIG_PC300_MLPPP
void cpc_tty_init(pc300dev_t * dev);
@@ -438,7 +437,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
printk("\n");
}
-static int dma_get_rx_frame_size(pc300_t * card, int ch)
+int dma_get_rx_frame_size(pc300_t * card, int ch)
{
volatile pcsca_bd_t __iomem *ptdescr;
ucshort first_bd = card->chan[ch].rx_first_bd;
@@ -463,7 +462,7 @@ static int dma_get_rx_frame_size(pc300_t * card, int ch)
* dma_buf_write: writes a frame to the Tx DMA buffers
* NOTE: this function writes one frame at a time.
*/
-static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
+int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
{
int i, nchar;
volatile pcsca_bd_t __iomem *ptdescr;
@@ -504,7 +503,7 @@ static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
* dma_buf_read: reads a frame from the Rx DMA buffers
* NOTE: this function reads one frame at a time.
*/
-static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
+int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
{
int nchar;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -561,7 +560,7 @@ static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
return (rcvd);
}
-static void tx_dma_stop(pc300_t * card, int ch)
+void tx_dma_stop(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
ucchar drr_ena_bit = 1 << (5 + 2 * ch);
@@ -572,7 +571,7 @@ static void tx_dma_stop(pc300_t * card, int ch)
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
}
-static void rx_dma_stop(pc300_t * card, int ch)
+void rx_dma_stop(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
ucchar drr_ena_bit = 1 << (4 + 2 * ch);
@@ -583,7 +582,7 @@ static void rx_dma_stop(pc300_t * card, int ch)
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
}
-static void rx_dma_start(pc300_t * card, int ch)
+void rx_dma_start(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -608,7 +607,7 @@ static void rx_dma_start(pc300_t * card, int ch)
/*************************/
/*** FALC Routines ***/
/*************************/
-static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
+void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
{
void __iomem *falcbase = card->hw.falcbase;
unsigned long i = 0;
@@ -623,7 +622,7 @@ static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
}
-static void falc_intr_enable(pc300_t * card, int ch)
+void falc_intr_enable(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -673,7 +672,7 @@ static void falc_intr_enable(pc300_t * card, int ch)
}
}
-static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
+void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
{
void __iomem *falcbase = card->hw.falcbase;
ucchar tshf = card->chan[ch].falc.offset;
@@ -689,7 +688,7 @@ static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
(0x80 >> (timeslot & 0x07)));
}
-static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
+void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
{
void __iomem *falcbase = card->hw.falcbase;
ucchar tshf = card->chan[ch].falc.offset;
@@ -705,7 +704,7 @@ static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
~(0x80 >> (timeslot & 0x07)));
}
-static void falc_close_all_timeslots(pc300_t * card, int ch)
+void falc_close_all_timeslots(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -727,7 +726,7 @@ static void falc_close_all_timeslots(pc300_t * card, int ch)
}
}
-static void falc_open_all_timeslots(pc300_t * card, int ch)
+void falc_open_all_timeslots(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -759,7 +758,7 @@ static void falc_open_all_timeslots(pc300_t * card, int ch)
}
}
-static void falc_init_timeslot(pc300_t * card, int ch)
+void falc_init_timeslot(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -777,7 +776,7 @@ static void falc_init_timeslot(pc300_t * card, int ch)
}
}
-static void falc_enable_comm(pc300_t * card, int ch)
+void falc_enable_comm(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -793,7 +792,7 @@ static void falc_enable_comm(pc300_t * card, int ch)
~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
}
-static void falc_disable_comm(pc300_t * card, int ch)
+void falc_disable_comm(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -807,7 +806,7 @@ static void falc_disable_comm(pc300_t * card, int ch)
((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
}
-static void falc_init_t1(pc300_t * card, int ch)
+void falc_init_t1(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -976,7 +975,7 @@ static void falc_init_t1(pc300_t * card, int ch)
falc_close_all_timeslots(card, ch);
}
-static void falc_init_e1(pc300_t * card, int ch)
+void falc_init_e1(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1156,7 +1155,7 @@ static void falc_init_e1(pc300_t * card, int ch)
falc_close_all_timeslots(card, ch);
}
-static void falc_init_hdlc(pc300_t * card, int ch)
+void falc_init_hdlc(pc300_t * card, int ch)
{
void __iomem *falcbase = card->hw.falcbase;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -1182,7 +1181,7 @@ static void falc_init_hdlc(pc300_t * card, int ch)
falc_intr_enable(card, ch);
}
-static void te_config(pc300_t * card, int ch)
+void te_config(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1242,7 +1241,7 @@ static void te_config(pc300_t * card, int ch)
CPC_UNLOCK(card, flags);
}
-static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
+void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1398,7 +1397,7 @@ static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
}
}
-static void falc_update_stats(pc300_t * card, int ch)
+void falc_update_stats(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1451,7 +1450,7 @@ static void falc_update_stats(pc300_t * card, int ch)
* the synchronizer and then sent to the system interface.
*----------------------------------------------------------------------------
*/
-static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
+void falc_remote_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1496,7 +1495,7 @@ static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
* coding must be identical.
*----------------------------------------------------------------------------
*/
-static void falc_local_loop(pc300_t * card, int ch, int loop_on)
+void falc_local_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1523,7 +1522,7 @@ static void falc_local_loop(pc300_t * card, int ch, int loop_on)
* looped. They are originated by the FALC-LH transmitter.
*----------------------------------------------------------------------------
*/
-static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
+void falc_payload_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1577,7 +1576,7 @@ static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
* Description: Turns XLU bit off in the proper register
*----------------------------------------------------------------------------
*/
-static void turn_off_xlu(pc300_t * card, int ch)
+void turn_off_xlu(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1598,7 +1597,7 @@ static void turn_off_xlu(pc300_t * card, int ch)
* Description: Turns XLD bit off in the proper register
*----------------------------------------------------------------------------
*/
-static void turn_off_xld(pc300_t * card, int ch)
+void turn_off_xld(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1620,7 +1619,7 @@ static void turn_off_xld(pc300_t * card, int ch)
* to generate a LOOP activation code over a T1/E1 line.
*----------------------------------------------------------------------------
*/
-static void falc_generate_loop_up_code(pc300_t * card, int ch)
+void falc_generate_loop_up_code(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1653,7 +1652,7 @@ static void falc_generate_loop_up_code(pc300_t * card, int ch)
* to generate a LOOP deactivation code over a T1/E1 line.
*----------------------------------------------------------------------------
*/
-static void falc_generate_loop_down_code(pc300_t * card, int ch)
+void falc_generate_loop_down_code(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1683,7 +1682,7 @@ static void falc_generate_loop_down_code(pc300_t * card, int ch)
* it on the reception side.
*----------------------------------------------------------------------------
*/
-static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
+void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1730,7 +1729,7 @@ static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
* Description: This routine returns the bit error counter value
*----------------------------------------------------------------------------
*/
-static ucshort falc_pattern_test_error(pc300_t * card, int ch)
+ucshort falc_pattern_test_error(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1770,7 +1769,7 @@ cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
netif_rx(skb);
}
-static void cpc_tx_timeout(struct net_device *dev)
+void cpc_tx_timeout(struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1798,7 +1797,7 @@ static void cpc_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1881,7 +1880,7 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-static void cpc_net_rx(struct net_device *dev)
+void cpc_net_rx(struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -2404,7 +2403,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static void cpc_sca_status(pc300_t * card, int ch)
+void cpc_sca_status(pc300_t * card, int ch)
{
ucchar ilar;
void __iomem *scabase = card->hw.scabase;
@@ -2496,7 +2495,7 @@ static void cpc_sca_status(pc300_t * card, int ch)
}
}
-static void cpc_falc_status(pc300_t * card, int ch)
+void cpc_falc_status(pc300_t * card, int ch)
{
pc300ch_t *chan = &card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -2524,7 +2523,7 @@ static void cpc_falc_status(pc300_t * card, int ch)
CPC_UNLOCK(card, flags);
}
-static int cpc_change_mtu(struct net_device *dev, int new_mtu)
+int cpc_change_mtu(struct net_device *dev, int new_mtu)
{
if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
return -EINVAL;
@@ -2532,7 +2531,7 @@ static int cpc_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
pc300dev_t *d = (pc300dev_t *) dev->priv;
@@ -2857,7 +2856,7 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
}
}
-static int ch_config(pc300dev_t * d)
+int ch_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -3005,7 +3004,7 @@ static int ch_config(pc300dev_t * d)
return 0;
}
-static int rx_config(pc300dev_t * d)
+int rx_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3036,7 +3035,7 @@ static int rx_config(pc300dev_t * d)
return 0;
}
-static int tx_config(pc300dev_t * d)
+int tx_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3099,7 +3098,7 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding,
return 0;
}
-static void cpc_opench(pc300dev_t * d)
+void cpc_opench(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3117,7 +3116,7 @@ static void cpc_opench(pc300dev_t * d)
cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
}
-static void cpc_closech(pc300dev_t * d)
+void cpc_closech(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3174,7 +3173,7 @@ int cpc_open(struct net_device *dev)
return 0;
}
-static int cpc_close(struct net_device *dev)
+int cpc_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
pc300dev_t *d = (pc300dev_t *) dev->priv;
diff --git a/trunk/drivers/net/wan/pc300_tty.c b/trunk/drivers/net/wan/pc300_tty.c
index 52f26b9c69d2..8454bf6caaa7 100644
--- a/trunk/drivers/net/wan/pc300_tty.c
+++ b/trunk/drivers/net/wan/pc300_tty.c
@@ -112,10 +112,10 @@ typedef struct _st_cpc_tty_area {
static struct tty_driver serial_drv;
/* local variables */
-static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
+st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
-static int cpc_tty_cnt = 0; /* number of intrfaces configured with MLPPP */
-static int cpc_tty_unreg_flag = 0;
+int cpc_tty_cnt=0; /* number of intrfaces configured with MLPPP */
+int cpc_tty_unreg_flag = 0;
/* TTY functions prototype */
static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
@@ -132,9 +132,9 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
-static int pc300_tiocmset(struct tty_struct *, struct file *,
- unsigned int, unsigned int);
-static int pc300_tiocmget(struct tty_struct *, struct file *);
+int pc300_tiocmset(struct tty_struct *, struct file *,
+ unsigned int, unsigned int);
+int pc300_tiocmget(struct tty_struct *, struct file *);
/* functions called by PC300 driver */
void cpc_tty_init(pc300dev_t *dev);
@@ -538,8 +538,8 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
return(0);
}
-static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
st_cpc_tty_area *cpc_tty;
@@ -565,7 +565,7 @@ static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+int pc300_tiocmget(struct tty_struct *tty, struct file *file)
{
unsigned int result;
unsigned char status;
diff --git a/trunk/drivers/net/wan/sdla.c b/trunk/drivers/net/wan/sdla.c
index 036adc4f8ba7..3ac9a45b20fa 100644
--- a/trunk/drivers/net/wan/sdla.c
+++ b/trunk/drivers/net/wan/sdla.c
@@ -182,7 +182,7 @@ static char sdla_byte(struct net_device *dev, int addr)
return(byte);
}
-static void sdla_stop(struct net_device *dev)
+void sdla_stop(struct net_device *dev)
{
struct frad_local *flp;
@@ -209,7 +209,7 @@ static void sdla_stop(struct net_device *dev)
}
}
-static void sdla_start(struct net_device *dev)
+void sdla_start(struct net_device *dev)
{
struct frad_local *flp;
@@ -247,7 +247,7 @@ static void sdla_start(struct net_device *dev)
*
***************************************************/
-static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
+int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
{
unsigned long start, done, now;
char resp, *temp;
@@ -505,7 +505,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
static int sdla_reconfig(struct net_device *dev);
-static int sdla_activate(struct net_device *slave, struct net_device *master)
+int sdla_activate(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -527,7 +527,7 @@ static int sdla_activate(struct net_device *slave, struct net_device *master)
return(0);
}
-static int sdla_deactivate(struct net_device *slave, struct net_device *master)
+int sdla_deactivate(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -549,7 +549,7 @@ static int sdla_deactivate(struct net_device *slave, struct net_device *master)
return(0);
}
-static int sdla_assoc(struct net_device *slave, struct net_device *master)
+int sdla_assoc(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -585,7 +585,7 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master)
return(0);
}
-static int sdla_deassoc(struct net_device *slave, struct net_device *master)
+int sdla_deassoc(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -613,7 +613,7 @@ static int sdla_deassoc(struct net_device *slave, struct net_device *master)
return(0);
}
-static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
+int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
{
struct frad_local *flp;
struct dlci_local *dlp;
@@ -1324,7 +1324,7 @@ NOTE: This is rather a useless action right now, as the
return(0);
}
-static int sdla_change_mtu(struct net_device *dev, int new_mtu)
+int sdla_change_mtu(struct net_device *dev, int new_mtu)
{
struct frad_local *flp;
@@ -1337,7 +1337,7 @@ static int sdla_change_mtu(struct net_device *dev, int new_mtu)
return(-EOPNOTSUPP);
}
-static int sdla_set_config(struct net_device *dev, struct ifmap *map)
+int sdla_set_config(struct net_device *dev, struct ifmap *map)
{
struct frad_local *flp;
int i;
diff --git a/trunk/drivers/net/wan/sdla_fr.c b/trunk/drivers/net/wan/sdla_fr.c
index 7f1ce9d4333e..0497dbdb8631 100644
--- a/trunk/drivers/net/wan/sdla_fr.c
+++ b/trunk/drivers/net/wan/sdla_fr.c
@@ -822,7 +822,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
chan->card = card;
/* verify media address */
- if (isdigit(conf->addr[0])) {
+ if (is_digit(conf->addr[0])) {
dlci = dec_to_uint(conf->addr, 0);
@@ -3456,7 +3456,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
if (!len)
len = strlen(str);
- for (val = 0; len && isdigit(*str); ++str, --len)
+ for (val = 0; len && is_digit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0');
return val;
diff --git a/trunk/drivers/net/wan/sdla_x25.c b/trunk/drivers/net/wan/sdla_x25.c
index 63f846d6f3a6..8a95d61a2f8f 100644
--- a/trunk/drivers/net/wan/sdla_x25.c
+++ b/trunk/drivers/net/wan/sdla_x25.c
@@ -957,7 +957,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
chan->hold_timeout = (conf->hold_timeout) ?
conf->hold_timeout : 10;
- }else if (isdigit(conf->addr[0])){ /* PVC */
+ }else if (is_digit(conf->addr[0])){ /* PVC */
int lcn = dec_to_uint(conf->addr, 0);
if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
@@ -3875,7 +3875,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
if (!len)
len = strlen(str);
- for (val = 0; len && isdigit(*str); ++str, --len)
+ for (val = 0; len && is_digit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0');
return val;
@@ -3896,9 +3896,9 @@ static unsigned int hex_to_uint (unsigned char* str, int len)
for (val = 0; len; ++str, --len)
{
ch = *str;
- if (isdigit(ch))
+ if (is_digit(ch))
val = (val << 4) + (ch - (unsigned)'0');
- else if (isxdigit(ch))
+ else if (is_hex_digit(ch))
val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
else break;
}
diff --git a/trunk/drivers/net/wan/sdladrv.c b/trunk/drivers/net/wan/sdladrv.c
index 7c2cf2e76300..c8bc6da57a41 100644
--- a/trunk/drivers/net/wan/sdladrv.c
+++ b/trunk/drivers/net/wan/sdladrv.c
@@ -642,7 +642,9 @@ int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
* Enable interrupt generation.
*/
-static int sdla_inten (sdlahw_t* hw)
+EXPORT_SYMBOL(sdla_inten);
+
+int sdla_inten (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
@@ -696,7 +698,8 @@ static int sdla_inten (sdlahw_t* hw)
* Disable interrupt generation.
*/
-#if 0
+EXPORT_SYMBOL(sdla_intde);
+
int sdla_intde (sdlahw_t* hw)
{
unsigned port = hw->port;
@@ -745,13 +748,14 @@ int sdla_intde (sdlahw_t* hw)
}
return 0;
}
-#endif /* 0 */
/*============================================================================
* Acknowledge SDLA hardware interrupt.
*/
-static int sdla_intack (sdlahw_t* hw)
+EXPORT_SYMBOL(sdla_intack);
+
+int sdla_intack (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp;
@@ -823,7 +827,8 @@ void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
* Generate an interrupt to adapter's CPU.
*/
-#if 0
+EXPORT_SYMBOL(sdla_intr);
+
int sdla_intr (sdlahw_t* hw)
{
unsigned port = hw->port;
@@ -858,7 +863,6 @@ int sdla_intr (sdlahw_t* hw)
}
return 0;
}
-#endif /* 0 */
/*============================================================================
* Execute Adapter Command.
diff --git a/trunk/drivers/net/wan/syncppp.c b/trunk/drivers/net/wan/syncppp.c
index 2d1bba06a085..a6d3b55013a5 100644
--- a/trunk/drivers/net/wan/syncppp.c
+++ b/trunk/drivers/net/wan/syncppp.c
@@ -221,7 +221,7 @@ static void sppp_clear_timeout(struct sppp *p)
* here.
*/
-static void sppp_input (struct net_device *dev, struct sk_buff *skb)
+void sppp_input (struct net_device *dev, struct sk_buff *skb)
{
struct ppp_header *h;
struct sppp *sp = (struct sppp *)sppp_of(dev);
@@ -355,6 +355,8 @@ static void sppp_input (struct net_device *dev, struct sk_buff *skb)
return;
}
+EXPORT_SYMBOL(sppp_input);
+
/*
* Handle transmit packets.
*/
@@ -988,7 +990,7 @@ EXPORT_SYMBOL(sppp_reopen);
* the mtu is out of range.
*/
-static int sppp_change_mtu(struct net_device *dev, int new_mtu)
+int sppp_change_mtu(struct net_device *dev, int new_mtu)
{
if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
return -EINVAL;
@@ -996,6 +998,8 @@ static int sppp_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+EXPORT_SYMBOL(sppp_change_mtu);
+
/**
* sppp_do_ioctl - Ioctl handler for ppp/hdlc
* @dev: Device subject to ioctl
@@ -1452,7 +1456,7 @@ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t
return 0;
}
-static struct packet_type sppp_packet_type = {
+struct packet_type sppp_packet_type = {
.type = __constant_htons(ETH_P_WAN_PPP),
.func = sppp_rcv,
};
diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c
index cb429e783749..06998c2240d9 100644
--- a/trunk/drivers/net/wireless/airo.c
+++ b/trunk/drivers/net/wireless/airo.c
@@ -1046,6 +1046,7 @@ static WifiCtlHdr wifictlhdr8023 = {
}
};
+#ifdef WIRELESS_EXT
// Frequency list (map channels to frequencies)
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
@@ -1066,6 +1067,7 @@ typedef struct wep_key_t {
/* List of Wireless Handlers (new API) */
static const struct iw_handler_def airo_handler_def;
+#endif /* WIRELESS_EXT */
static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
@@ -1108,8 +1110,10 @@ static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
static int airo_thread(void *data);
static void timer_func( struct net_device *dev );
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#ifdef WIRELESS_EXT
static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
static void airo_read_wireless_stats (struct airo_info *local);
+#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
@@ -1183,10 +1187,12 @@ struct airo_info {
int fid;
} xmit, xmit11;
struct net_device *wifidev;
+#ifdef WIRELESS_EXT
struct iw_statistics wstats; // wireless stats
unsigned long scan_timestamp; /* Time started to scan */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
+#endif /* WIRELESS_EXT */
#ifdef MICSUPPORT
/* MIC stuff */
struct crypto_tfm *tfm;
@@ -2521,8 +2527,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
unsigned long mem_start, mem_len, aux_start, aux_len;
int rc = -1;
int i;
- dma_addr_t busaddroff;
- unsigned char *vpackoff;
+ unsigned char *busaddroff,*vpackoff;
unsigned char __iomem *pciaddroff;
mem_start = pci_resource_start(pci, 1);
@@ -2565,7 +2570,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/*
* Setup descriptor RX, TX, CONFIG
*/
- busaddroff = ai->shared_dma;
+ busaddroff = (unsigned char *)ai->shared_dma;
pciaddroff = ai->pciaux + AUX_OFFSET;
vpackoff = ai->shared;
@@ -2574,7 +2579,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
ai->rxfids[i].pending = 0;
ai->rxfids[i].card_ram_off = pciaddroff;
ai->rxfids[i].virtual_host_addr = vpackoff;
- ai->rxfids[i].rx_desc.host_addr = busaddroff;
+ ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
ai->rxfids[i].rx_desc.valid = 1;
ai->rxfids[i].rx_desc.len = PKTSIZE;
ai->rxfids[i].rx_desc.rdy = 0;
@@ -2589,7 +2594,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
ai->txfids[i].card_ram_off = pciaddroff;
ai->txfids[i].virtual_host_addr = vpackoff;
ai->txfids[i].tx_desc.valid = 1;
- ai->txfids[i].tx_desc.host_addr = busaddroff;
+ ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
memcpy(ai->txfids[i].virtual_host_addr,
&wifictlhdr8023, sizeof(wifictlhdr8023));
@@ -2602,8 +2607,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/* Rid descriptor setup */
ai->config_desc.card_ram_off = pciaddroff;
ai->config_desc.virtual_host_addr = vpackoff;
- ai->config_desc.rid_desc.host_addr = busaddroff;
- ai->ridbus = busaddroff;
+ ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->ridbus = (dma_addr_t)busaddroff;
ai->config_desc.rid_desc.rid = 0;
ai->config_desc.rid_desc.len = RIDSIZE;
ai->config_desc.rid_desc.valid = 1;
@@ -2642,7 +2647,9 @@ static void wifi_setup(struct net_device *dev)
dev->get_stats = &airo_get_stats;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
+#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
+#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
@@ -2668,7 +2675,9 @@ static struct net_device *init_wifidev(struct airo_info *ai,
dev->priv = ethdev->priv;
dev->irq = ethdev->irq;
dev->base_addr = ethdev->base_addr;
+#ifdef WIRELESS_EXT
dev->wireless_data = ethdev->wireless_data;
+#endif /* WIRELESS_EXT */
memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
err = register_netdev(dev);
if (err<0) {
@@ -2746,9 +2755,11 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
dev->set_multicast_list = &airo_set_multicast_list;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
+#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
ai->wireless_data.spy_data = &ai->spy_data;
dev->wireless_data = &ai->wireless_data;
+#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
@@ -5504,13 +5515,12 @@ static int airo_pci_resume(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct airo_info *ai = dev->priv;
Resp rsp;
- pci_power_t prev_state = pdev->current_state;
- pci_set_power_state(pdev, PCI_D0);
+ pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
- pci_enable_wake(pdev, PCI_D0, 0);
+ pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
- if (prev_state != PCI_D1) {
+ if (ai->power.event > 1) {
reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
@@ -5588,6 +5598,7 @@ static void __exit airo_cleanup_module( void )
remove_proc_entry("aironet", proc_root_driver);
}
+#ifdef WIRELESS_EXT
/*
* Initial Wireless Extension code for Aironet driver by :
* Jean Tourrilhes - HPL - 17 November 00
@@ -7096,6 +7107,8 @@ static const struct iw_handler_def airo_handler_def =
.get_wireless_stats = airo_get_wireless_stats,
};
+#endif /* WIRELESS_EXT */
+
/*
* This defines the configuration part of the Wireless Extensions
* Note : irq and spinlock protection will occur in the subroutines
@@ -7174,6 +7187,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
+#ifdef WIRELESS_EXT
/*
* Get the Wireless stats out of the driver
* Note : irq and spinlock protection will occur in the subroutines
@@ -7246,6 +7260,7 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
return &local->wstats;
}
+#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
/*
diff --git a/trunk/drivers/net/wireless/airport.c b/trunk/drivers/net/wireless/airport.c
index 7b321f7cf358..9d496703c465 100644
--- a/trunk/drivers/net/wireless/airport.c
+++ b/trunk/drivers/net/wireless/airport.c
@@ -15,11 +15,28 @@
#define PFX DRIVER_NAME ": "
#include
+
#include
#include
#include
-#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
#include
+#include
+#include
#include "orinoco.h"
diff --git a/trunk/drivers/net/wireless/atmel.c b/trunk/drivers/net/wireless/atmel.c
index d57011028b72..587869d86eee 100644
--- a/trunk/drivers/net/wireless/atmel.c
+++ b/trunk/drivers/net/wireless/atmel.c
@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
static void atmel_command_irq(struct atmel_private *priv);
static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 frame_len, u8 rssi);
static void atmel_management_timer(u_long a);
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
static int start_tx (struct sk_buff *skb, struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u8 *body, int body_len)
{
u16 buff;
@@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
@@ -990,7 +990,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return (crc ^ 0xffffffff) == netcrc;
}
-static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
{
u8 mac4[6];
@@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
static void rx_done_irq(struct atmel_private *priv)
{
int i;
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -2650,7 +2650,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
{
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
struct auth_body auth;
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
@@ -2688,7 +2688,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
{
u8 *ssid_el_p;
int bodysize;
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
struct ass_req_format {
u16 capability;
u16 listen_interval;
@@ -2738,7 +2738,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
}
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
{
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
@@ -2788,7 +2788,7 @@ static int retrieve_bss(struct atmel_private *priv)
}
-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
u8 ssid_len, u8 *ssid, int is_beacon)
{
@@ -3072,7 +3072,7 @@ static void atmel_smooth_qual(struct atmel_private *priv)
}
/* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 frame_len, u8 rssi)
{
u16 subtype;
diff --git a/trunk/drivers/net/wireless/hermes.c b/trunk/drivers/net/wireless/hermes.c
index eba0d9d2b7c5..21c3d0d227e6 100644
--- a/trunk/drivers/net/wireless/hermes.c
+++ b/trunk/drivers/net/wireless/hermes.c
@@ -39,10 +39,17 @@
*/
#include
+
#include
-#include
-#include
+#include
+#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
#include "hermes.h"
diff --git a/trunk/drivers/net/wireless/hermes.h b/trunk/drivers/net/wireless/hermes.h
index ad28e3294360..8c9e874c9118 100644
--- a/trunk/drivers/net/wireless/hermes.h
+++ b/trunk/drivers/net/wireless/hermes.h
@@ -30,8 +30,9 @@
* access to the hermes_t structure, and to the hardware
*/
+#include
#include
-#include
+#include
/*
* Limits and constants
@@ -191,13 +192,13 @@
#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
struct hermes_tx_descriptor {
- __le16 status;
- __le16 reserved1;
- __le16 reserved2;
- __le32 sw_support;
+ u16 status;
+ u16 reserved1;
+ u16 reserved2;
+ u32 sw_support;
u8 retry_count;
u8 tx_rate;
- __le16 tx_control;
+ u16 tx_control;
} __attribute__ ((packed));
#define HERMES_TXSTAT_RETRYERR (0x0001)
@@ -221,60 +222,60 @@ struct hermes_tx_descriptor {
#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
struct hermes_tallies_frame {
- __le16 TxUnicastFrames;
- __le16 TxMulticastFrames;
- __le16 TxFragments;
- __le16 TxUnicastOctets;
- __le16 TxMulticastOctets;
- __le16 TxDeferredTransmissions;
- __le16 TxSingleRetryFrames;
- __le16 TxMultipleRetryFrames;
- __le16 TxRetryLimitExceeded;
- __le16 TxDiscards;
- __le16 RxUnicastFrames;
- __le16 RxMulticastFrames;
- __le16 RxFragments;
- __le16 RxUnicastOctets;
- __le16 RxMulticastOctets;
- __le16 RxFCSErrors;
- __le16 RxDiscards_NoBuffer;
- __le16 TxDiscardsWrongSA;
- __le16 RxWEPUndecryptable;
- __le16 RxMsgInMsgFragments;
- __le16 RxMsgInBadMsgFragments;
+ u16 TxUnicastFrames;
+ u16 TxMulticastFrames;
+ u16 TxFragments;
+ u16 TxUnicastOctets;
+ u16 TxMulticastOctets;
+ u16 TxDeferredTransmissions;
+ u16 TxSingleRetryFrames;
+ u16 TxMultipleRetryFrames;
+ u16 TxRetryLimitExceeded;
+ u16 TxDiscards;
+ u16 RxUnicastFrames;
+ u16 RxMulticastFrames;
+ u16 RxFragments;
+ u16 RxUnicastOctets;
+ u16 RxMulticastOctets;
+ u16 RxFCSErrors;
+ u16 RxDiscards_NoBuffer;
+ u16 TxDiscardsWrongSA;
+ u16 RxWEPUndecryptable;
+ u16 RxMsgInMsgFragments;
+ u16 RxMsgInBadMsgFragments;
/* Those last are probably not available in very old firmwares */
- __le16 RxDiscards_WEPICVError;
- __le16 RxDiscards_WEPExcluded;
+ u16 RxDiscards_WEPICVError;
+ u16 RxDiscards_WEPExcluded;
} __attribute__ ((packed));
/* Grabbed from wlan-ng - Thanks Mark... - Jean II
* This is the result of a scan inquiry command */
/* Structure describing info about an Access Point */
struct prism2_scan_apinfo {
- __le16 channel; /* Channel where the AP sits */
- __le16 noise; /* Noise level */
- __le16 level; /* Signal level */
+ u16 channel; /* Channel where the AP sits */
+ u16 noise; /* Noise level */
+ u16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- __le16 beacon_interv; /* Beacon interval */
- __le16 capabilities; /* Capabilities */
- __le16 essid_len; /* ESSID length */
+ u16 beacon_interv; /* Beacon interval */
+ u16 capabilities; /* Capabilities */
+ u16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
u8 rates[10]; /* Bit rate supported */
- __le16 proberesp_rate; /* Data rate of the response frame */
- __le16 atim; /* ATIM window time, Kus (hostscan only) */
+ u16 proberesp_rate; /* Data rate of the response frame */
+ u16 atim; /* ATIM window time, Kus (hostscan only) */
} __attribute__ ((packed));
/* Same stuff for the Lucent/Agere card.
* Thanks to h1kari - Jean II */
struct agere_scan_apinfo {
- __le16 channel; /* Channel where the AP sits */
- __le16 noise; /* Noise level */
- __le16 level; /* Signal level */
+ u16 channel; /* Channel where the AP sits */
+ u16 noise; /* Noise level */
+ u16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- __le16 beacon_interv; /* Beacon interval */
- __le16 capabilities; /* Capabilities */
+ u16 beacon_interv; /* Beacon interval */
+ u16 capabilities; /* Capabilities */
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
- __le16 essid_len; /* ESSID length */
+ u16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
} __attribute__ ((packed));
@@ -282,16 +283,16 @@ struct agere_scan_apinfo {
struct symbol_scan_apinfo {
u8 channel; /* Channel where the AP sits */
u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
- __le16 noise; /* Noise level */
- __le16 level; /* Signal level */
+ u16 noise; /* Noise level */
+ u16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- __le16 beacon_interv; /* Beacon interval */
- __le16 capabilities; /* Capabilities */
+ u16 beacon_interv; /* Beacon interval */
+ u16 capabilities; /* Capabilities */
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
- __le16 essid_len; /* ESSID length */
+ u16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
- __le16 rates[5]; /* Bit rate supported */
- __le16 basic_rates; /* Basic rates bitmask */
+ u16 rates[5]; /* Bit rate supported */
+ u16 basic_rates; /* Basic rates bitmask */
u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
} __attribute__ ((packed));
@@ -311,7 +312,7 @@ union hermes_scan_info {
#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
struct hermes_linkstatus {
- __le16 linkstatus; /* Link status */
+ u16 linkstatus; /* Link status */
} __attribute__ ((packed));
struct hermes_response {
@@ -320,8 +321,8 @@ struct hermes_response {
/* "ID" structure - used for ESSID and station nickname */
struct hermes_idstring {
- __le16 len;
- __le16 val[16];
+ u16 len;
+ u16 val[16];
} __attribute__ ((packed));
struct hermes_multicast {
@@ -446,7 +447,7 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count
static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
{
- __le16 rec;
+ u16 rec;
int err;
err = HERMES_READ_RECORD(hw, bap, rid, &rec);
@@ -456,7 +457,7 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
{
- __le16 rec = cpu_to_le16(word);
+ u16 rec = cpu_to_le16(word);
return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
}
diff --git a/trunk/drivers/net/wireless/hostap/hostap.c b/trunk/drivers/net/wireless/hostap/hostap.c
index 6a96cd9f2685..e7f5821b4942 100644
--- a/trunk/drivers/net/wireless/hostap/hostap.c
+++ b/trunk/drivers/net/wireless/hostap/hostap.c
@@ -716,6 +716,9 @@ static int prism2_close(struct net_device *dev)
hostap_deauth_all_stas(dev, local->ap, 1);
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ if (local->func->dev_close && local->func->dev_close(local))
+ return 0;
+
if (dev == local->dev) {
local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
}
@@ -763,6 +766,9 @@ static int prism2_open(struct net_device *dev)
local->hw_downloading)
return -ENODEV;
+ if (local->func->dev_open && local->func->dev_open(local))
+ return 1;
+
if (!try_module_get(local->hw_module))
return -ENODEV;
local->num_dev_open++;
diff --git a/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c b/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c
index ffac50899454..b0501243b175 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -6,10 +6,10 @@
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
"jiffies=%ld\n",
@@ -51,7 +51,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
int hdrlen, phdrlen, head_need, tail_need;
u16 fc;
int prism_header, ret;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@@ -70,7 +70,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
phdrlen = 0;
}
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
@@ -215,7 +215,7 @@ prism2_frag_cache_find(local_info_t *local, unsigned int seq,
/* Called only as a tasklet (software IRQ) */
static struct sk_buff *
-prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
{
struct sk_buff *skb = NULL;
u16 sc;
@@ -229,7 +229,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
if (frag == 0) {
/* Reserve enough space to fit maximum frame length */
skb = dev_alloc_skb(local->dev->mtu +
- sizeof(struct ieee80211_hdr_4addr) +
+ sizeof(struct ieee80211_hdr) +
8 /* LLC */ +
2 /* alignment */ +
8 /* WEP */ + ETH_ALEN /* WDS */);
@@ -267,7 +267,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
/* Called only as a tasklet (software IRQ) */
static int prism2_frag_cache_invalidate(local_info_t *local,
- struct ieee80211_hdr_4addr *hdr)
+ struct ieee80211_hdr *hdr)
{
u16 sc;
unsigned int seq;
@@ -441,7 +441,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
u16 stype)
{
if (local->iw_mode == IW_MODE_MASTER) {
- hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
+ hostap_update_sta_ps(local, (struct ieee80211_hdr *)
skb->data);
}
@@ -520,7 +520,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
static inline int
-hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
u16 fc, struct net_device **wds)
{
/* FIX: is this really supposed to accept WDS frames only in Master
@@ -579,13 +579,13 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
{
struct net_device *dev = local->dev;
u16 fc, ethertype;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u8 *pos;
if (skb->len < 24)
return 0;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
/* check that the frame is unicast frame to us */
@@ -619,13 +619,13 @@ static inline int
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
struct ieee80211_crypt_data *crypt)
{
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
int res, hdrlen;
if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
return 0;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
if (local->tkip_countermeasures &&
@@ -658,13 +658,13 @@ static inline int
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
int keyidx, struct ieee80211_crypt_data *crypt)
{
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
int res, hdrlen;
if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
return 0;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
atomic_inc(&crypt->refcnt);
@@ -689,7 +689,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
size_t hdrlen;
u16 fc, type, stype, sc;
struct net_device *wds = NULL;
@@ -716,7 +716,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
dev = local->ddev;
iface = netdev_priv(dev);
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
stats = hostap_get_stats(dev);
if (skb->len < 10)
@@ -737,8 +737,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
struct iw_quality wstats;
wstats.level = rx_stats->signal;
wstats.noise = rx_stats->noise;
- wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
- | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
+ wstats.updated = 6; /* No qual value */
/* Update spy records */
wireless_spy_update(dev, hdr->addr2, &wstats);
}
@@ -890,7 +889,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
(keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
goto rx_dropped;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
/* skb: hdr + (possibly fragmented) plaintext payload */
@@ -942,7 +941,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
/* this was the last fragment and the frame will be
* delivered, so remove skb from fragment cache */
skb = frag_skb;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
prism2_frag_cache_invalidate(local, hdr);
}
@@ -953,7 +952,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
goto rx_dropped;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
if (local->ieee_802_1x &&
hostap_is_eapol_frame(local, skb)) {
diff --git a/trunk/drivers/net/wireless/hostap/hostap_80211_tx.c b/trunk/drivers/net/wireless/hostap/hostap_80211_tx.c
index 9d24f8a38ac5..6358015f6526 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,9 +1,9 @@
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
name, skb->len, jiffies);
@@ -41,7 +41,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hostap_interface *iface;
local_info_t *local;
int need_headroom, need_tailroom = 0;
- struct ieee80211_hdr_4addr hdr;
+ struct ieee80211_hdr hdr;
u16 fc, ethertype = 0;
enum {
WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
@@ -244,7 +244,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hostap_interface *iface;
local_info_t *local;
struct hostap_skb_tx_data *meta;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc;
iface = netdev_priv(dev);
@@ -266,7 +266,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
meta->iface = iface;
if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
@@ -289,7 +289,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc;
int hdr_len, res;
@@ -303,7 +303,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
if (local->tkip_countermeasures &&
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
"TX packet to " MACSTR "\n",
@@ -317,15 +317,15 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
if (skb == NULL)
return NULL;
- if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
- skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
- pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
- crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
+ if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
+ skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
+ pskb_expand_head(skb, crypt->ops->extra_prefix_len,
+ crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
kfree_skb(skb);
return NULL;
}
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
hdr_len = hostap_80211_get_hdrlen(fc);
@@ -360,7 +360,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
ap_tx_ret tx_ret;
struct hostap_skb_tx_data *meta;
int no_encrypt = 0;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@@ -403,7 +403,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_ret = hostap_handle_sta_tx(local, &tx);
skb = tx.skb;
meta = (struct hostap_skb_tx_data *) skb->cb;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
switch (tx_ret) {
case AP_TX_CONTINUE:
diff --git a/trunk/drivers/net/wireless/hostap/hostap_ap.c b/trunk/drivers/net/wireless/hostap/hostap_ap.c
index 9da94ab7f05f..930cef8367f2 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_ap.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_ap.c
@@ -591,14 +591,14 @@ static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
u16 fc;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
if (!ap->local->hostapd || !ap->local->apdev) {
dev_kfree_skb(skb);
return;
}
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
/* Pass the TX callback frame to the hostapd; use 802.11 header version
@@ -623,7 +623,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc, *pos, auth_alg, auth_transaction, status;
struct sta_info *sta = NULL;
char *txt = NULL;
@@ -633,7 +633,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
return;
}
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
@@ -692,7 +692,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc, *pos, status;
struct sta_info *sta = NULL;
char *txt = NULL;
@@ -702,7 +702,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
return;
}
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
(WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
@@ -757,12 +757,12 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
struct sta_info *sta;
if (skb->len < 24)
goto fail;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
if (ok) {
spin_lock(&ap->sta_table_lock);
sta = ap_get_sta(ap, hdr->addr1);
@@ -918,7 +918,7 @@ static void prism2_send_mgmt(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
u16 fc;
struct sk_buff *skb;
struct hostap_skb_tx_data *meta;
@@ -944,7 +944,7 @@ static void prism2_send_mgmt(struct net_device *dev,
fc = type_subtype;
hdrlen = hostap_80211_get_hdrlen(fc);
- hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
+ hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
if (body)
memcpy(skb_put(skb, body_len), body, body_len);
@@ -1256,14 +1256,14 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
}
skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
- ap->crypt->extra_mpdu_prefix_len +
- ap->crypt->extra_mpdu_postfix_len);
+ ap->crypt->extra_prefix_len +
+ ap->crypt->extra_postfix_len);
if (skb == NULL) {
kfree(tmpbuf);
return NULL;
}
- skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
+ skb_reserve(skb, ap->crypt->extra_prefix_len);
memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
WLAN_AUTH_CHALLENGE_LEN);
if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
@@ -1272,7 +1272,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
return NULL;
}
- memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
+ memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
WLAN_AUTH_CHALLENGE_LEN);
dev_kfree_skb(skb);
@@ -1285,7 +1285,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
size_t hdrlen;
struct ap_data *ap = local->ap;
char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
@@ -1498,7 +1498,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, int reassoc)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char body[12], *p, *lpos;
int len, left;
u16 *pos;
@@ -1705,7 +1705,7 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
int len;
u16 reason_code, *pos;
@@ -1746,7 +1746,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len;
u16 reason_code, *pos;
@@ -1784,7 +1784,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
/* Called only as a scheduled task for pending AP frames. */
static void ap_handle_data_nullfunc(local_info_t *local,
- struct ieee80211_hdr_4addr *hdr)
+ struct ieee80211_hdr *hdr)
{
struct net_device *dev = local->dev;
@@ -1801,7 +1801,7 @@ static void ap_handle_data_nullfunc(local_info_t *local,
/* Called only as a scheduled task for pending AP frames. */
static void ap_handle_dropped_data(local_info_t *local,
- struct ieee80211_hdr_4addr *hdr)
+ struct ieee80211_hdr *hdr)
{
struct net_device *dev = local->dev;
struct sta_info *sta;
@@ -1860,7 +1860,7 @@ static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
/* Called only as a scheduled task for pending AP frames. */
static void handle_pspoll(local_info_t *local,
- struct ieee80211_hdr_4addr *hdr,
+ struct ieee80211_hdr *hdr,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
@@ -1979,7 +1979,7 @@ static void handle_wds_oper_queue(void *data)
static void handle_beacon(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
- struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len, left;
u16 *pos, beacon_int, capability;
@@ -2137,11 +2137,11 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
struct net_device *dev = local->dev;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
u16 fc, type, stype;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
/* FIX: should give skb->len to handler functions and check that the
* buffer is long enough */
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
@@ -2258,7 +2258,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
struct hostap_interface *iface;
local_info_t *local;
u16 fc;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@@ -2268,7 +2268,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
local->stats.rx_packets++;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
@@ -2289,7 +2289,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
{
struct sk_buff *skb;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
struct hostap_80211_rx_status rx_stats;
if (skb_queue_empty(&sta->tx_buf))
@@ -2302,7 +2302,7 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
return;
}
- hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
+ hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
/* Generate a fake pspoll frame to start packet delivery */
hdr->frame_ctl = __constant_cpu_to_le16(
@@ -2349,7 +2349,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
qual[count].updated = sta->last_rx_updated;
- sta->last_rx_updated = IW_QUAL_DBM;
+ sta->last_rx_updated = 0;
count++;
if (count >= buf_size)
@@ -2467,7 +2467,7 @@ static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
}
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
- sta->last_rx_updated = IW_QUAL_DBM;
+ sta->last_rx_updated = 0;
/* To be continued, we should make good use of IWEVCUSTOM */
}
@@ -2685,7 +2685,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
struct sta_info *sta = NULL;
struct sk_buff *skb = tx->skb;
int set_tim, ret;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
struct hostap_skb_tx_data *meta;
meta = (struct hostap_skb_tx_data *) skb->cb;
@@ -2694,7 +2694,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
meta->iface->type == HOSTAP_INTERFACE_STA)
goto out;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
@@ -2821,10 +2821,10 @@ void hostap_handle_sta_release(void *ptr)
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
{
struct sta_info *sta;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
struct hostap_skb_tx_data *meta;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
meta = (struct hostap_skb_tx_data *) skb->cb;
spin_lock(&local->ap->sta_table_lock);
@@ -2892,7 +2892,7 @@ static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
/* Called only as a tasklet (software IRQ). Called for each RX frame to update
* STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
{
struct sta_info *sta;
u16 fc;
@@ -2925,12 +2925,12 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
int ret;
struct sta_info *sta;
u16 fc, type, stype;
- struct ieee80211_hdr_4addr *hdr;
+ struct ieee80211_hdr *hdr;
if (local->ap == NULL)
return AP_RX_CONTINUE;
- hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
@@ -3058,7 +3058,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
/* Called only as a tasklet (software IRQ) */
int hostap_handle_sta_crypto(local_info_t *local,
- struct ieee80211_hdr_4addr *hdr,
+ struct ieee80211_hdr *hdr,
struct ieee80211_crypt_data **crypt,
void **sta_ptr)
{
@@ -3160,7 +3160,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
/* Called only as a tasklet (software IRQ) */
int hostap_update_rx_stats(struct ap_data *ap,
- struct ieee80211_hdr_4addr *hdr,
+ struct ieee80211_hdr *hdr,
struct hostap_80211_rx_status *rx_stats)
{
struct sta_info *sta;
@@ -3174,7 +3174,7 @@ int hostap_update_rx_stats(struct ap_data *ap,
sta->last_rx_silence = rx_stats->noise;
sta->last_rx_signal = rx_stats->signal;
sta->last_rx_rate = rx_stats->rate;
- sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ sta->last_rx_updated = 7;
if (rx_stats->rate == 10)
sta->rx_count[0]++;
else if (rx_stats->rate == 20)
diff --git a/trunk/drivers/net/wireless/hostap/hostap_ap.h b/trunk/drivers/net/wireless/hostap/hostap_ap.h
index 6d00df69c2e3..816a52bcea8f 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_ap.h
+++ b/trunk/drivers/net/wireless/hostap/hostap_ap.h
@@ -233,7 +233,7 @@ struct hostap_tx_data {
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
void hostap_handle_sta_release(void *ptr);
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
typedef enum {
AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
} ap_rx_ret;
@@ -241,13 +241,13 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats,
int wds);
-int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
+int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
struct ieee80211_crypt_data **crypt,
void **sta_ptr);
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
-int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
+int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
struct hostap_80211_rx_status *rx_stats);
void hostap_update_rates(local_info_t *local);
void hostap_add_wds_links(local_info_t *local);
diff --git a/trunk/drivers/net/wireless/hostap/hostap_cs.c b/trunk/drivers/net/wireless/hostap/hostap_cs.c
index 2643976a6677..faa83badf0a1 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_cs.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_cs.c
@@ -492,10 +492,42 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
}
+static int prism2_pccard_dev_open(local_info_t *local)
+{
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+ hw_priv->link->open++;
+ return 0;
+}
+
+
+static int prism2_pccard_dev_close(local_info_t *local)
+{
+ struct hostap_cs_priv *hw_priv;
+
+ if (local == NULL || local->hw_priv == NULL)
+ return 1;
+ hw_priv = local->hw_priv;
+ if (hw_priv->link == NULL)
+ return 1;
+
+ if (!hw_priv->link->open) {
+ printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
+ "link not open?!\n", local->dev->name);
+ return 1;
+ }
+
+ hw_priv->link->open--;
+
+ return 0;
+}
+
+
static struct prism2_helper_functions prism2_pccard_funcs =
{
.card_present = prism2_pccard_card_present,
.cor_sreset = prism2_pccard_cor_sreset,
+ .dev_open = prism2_pccard_dev_open,
+ .dev_close = prism2_pccard_dev_close,
.genesis_reset = prism2_pccard_genesis_reset,
.hw_type = HOSTAP_HW_PCCARD,
};
@@ -565,14 +597,13 @@ static void prism2_detach(dev_link_t *link)
*linkp = link->next;
/* release net devices */
if (link->priv) {
- struct hostap_cs_priv *hw_priv;
struct net_device *dev;
struct hostap_interface *iface;
dev = link->priv;
iface = netdev_priv(dev);
- hw_priv = iface->local->hw_priv;
+ kfree(iface->local->hw_priv);
+ iface->local->hw_priv = NULL;
prism2_free_local_data(dev);
- kfree(hw_priv);
}
kfree(link);
}
@@ -852,13 +883,6 @@ static int prism2_event(event_t event, int priority,
{
dev_link_t *link = args->client_data;
struct net_device *dev = (struct net_device *) link->priv;
- int dev_open = 0;
-
- if (link->state & DEV_CONFIG) {
- struct hostap_interface *iface = netdev_priv(dev);
- if (iface && iface->local)
- dev_open = iface->local->num_dev_open > 0;
- }
switch (event) {
case CS_EVENT_CARD_INSERTION:
@@ -887,7 +911,7 @@ static int prism2_event(event_t event, int priority,
case CS_EVENT_RESET_PHYSICAL:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
if (link->state & DEV_CONFIG) {
- if (dev_open) {
+ if (link->open) {
netif_stop_queue(dev);
netif_device_detach(dev);
}
@@ -907,8 +931,8 @@ static int prism2_event(event_t event, int priority,
pcmcia_request_configuration(link->handle,
&link->conf);
prism2_hw_shutdown(dev, 1);
- prism2_hw_config(dev, dev_open ? 0 : 1);
- if (dev_open) {
+ prism2_hw_config(dev, link->open ? 0 : 1);
+ if (link->open) {
netif_device_attach(dev);
netif_start_queue(dev);
}
diff --git a/trunk/drivers/net/wireless/hostap/hostap_hw.c b/trunk/drivers/net/wireless/hostap/hostap_hw.c
index 59fc15572395..e533a663deda 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_hw.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_hw.c
@@ -3322,18 +3322,6 @@ static void prism2_free_local_data(struct net_device *dev)
iface = netdev_priv(dev);
local = iface->local;
- /* Unregister all netdevs before freeing local data. */
- list_for_each_safe(ptr, n, &local->hostap_interfaces) {
- iface = list_entry(ptr, struct hostap_interface, list);
- if (iface->type == HOSTAP_INTERFACE_MASTER) {
- /* special handling for this interface below */
- continue;
- }
- hostap_remove_interface(iface->dev, 0, 1);
- }
-
- unregister_netdev(local->dev);
-
flush_scheduled_work();
if (timer_pending(&local->crypt_deinit_timer))
@@ -3394,6 +3382,15 @@ static void prism2_free_local_data(struct net_device *dev)
prism2_download_free_data(local->dl_sec);
#endif /* PRISM2_DOWNLOAD_SUPPORT */
+ list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type == HOSTAP_INTERFACE_MASTER) {
+ /* special handling for this interface below */
+ continue;
+ }
+ hostap_remove_interface(iface->dev, 0, 1);
+ }
+
prism2_clear_set_tim_queue(local);
list_for_each_safe(ptr, n, &local->bss_list) {
@@ -3406,6 +3403,7 @@ static void prism2_free_local_data(struct net_device *dev)
kfree(local->last_scan_results);
kfree(local->generic_elem);
+ unregister_netdev(local->dev);
free_netdev(local->dev);
}
diff --git a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c
index 53f5246c40aa..e720369a3515 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -50,8 +50,7 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
#endif /* in_atomic */
if (update && prism2_update_comms_qual(dev) == 0)
- wstats->qual.updated = IW_QUAL_ALL_UPDATED |
- IW_QUAL_DBM;
+ wstats->qual.updated = 7;
wstats->qual.qual = local->comms_qual;
wstats->qual.level = local->avg_signal;
@@ -60,7 +59,7 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
wstats->qual.qual = 0;
wstats->qual.level = 0;
wstats->qual.noise = 0;
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
+ wstats->qual.updated = 0;
}
return wstats;
@@ -1828,6 +1827,13 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
+ /* FIX:
+ * I do not know how this is possible, but iwe_stream_add_event
+ * seems to re-order memcpy execution so that len is set only
+ * after copying.. Pre-setting len here "fixes" this, but real
+ * problems should be solved (after which these iwe.len
+ * settings could be removed from this function). */
+ iwe.len = IW_EV_ADDR_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_ADDR_LEN);
@@ -1837,6 +1843,7 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.cmd = SIOCGIWESSID;
iwe.u.data.length = ssid_len;
iwe.u.data.flags = 1;
+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
memset(&iwe, 0, sizeof(iwe));
@@ -1852,6 +1859,7 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.u.mode = IW_MODE_MASTER;
else
iwe.u.mode = IW_MODE_ADHOC;
+ iwe.len = IW_EV_UINT_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_UINT_LEN);
}
@@ -1869,6 +1877,7 @@ static char * __prism2_translate_scan(local_info_t *local,
if (chan > 0) {
iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
iwe.u.freq.e = 1;
+ iwe.len = IW_EV_FREQ_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_FREQ_LEN);
}
@@ -1885,10 +1894,7 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.u.qual.noise =
HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
}
- iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED
- | IW_QUAL_QUAL_INVALID
- | IW_QUAL_DBM;
+ iwe.len = IW_EV_QUAL_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_QUAL_LEN);
}
@@ -1900,6 +1906,7 @@ static char * __prism2_translate_scan(local_info_t *local,
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
/* TODO: add SuppRates into BSS table */
@@ -1923,7 +1930,7 @@ static char * __prism2_translate_scan(local_info_t *local,
}
/* TODO: add BeaconInt,resp_rate,atim into BSS table */
- buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
+ buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
if (buf && scan) {
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
diff --git a/trunk/drivers/net/wireless/hostap/hostap_pci.c b/trunk/drivers/net/wireless/hostap/hostap_pci.c
index da0c80fb941c..025f8cdb5566 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_pci.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_pci.c
@@ -59,13 +59,11 @@ static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
{
struct hostap_interface *iface;
- struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
iface = netdev_priv(dev);
local = iface->local;
- hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
@@ -76,14 +74,12 @@ static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
{
struct hostap_interface *iface;
- struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
u8 v;
iface = netdev_priv(dev);
local = iface->local;
- hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
v = readb(hw_priv->mem_start + a);
@@ -95,13 +91,11 @@ static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
{
struct hostap_interface *iface;
- struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
iface = netdev_priv(dev);
local = iface->local;
- hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
@@ -112,14 +106,12 @@ static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
{
struct hostap_interface *iface;
- struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
u16 v;
iface = netdev_priv(dev);
local = iface->local;
- hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
v = readw(hw_priv->mem_start + a);
@@ -285,6 +277,8 @@ static struct prism2_helper_functions prism2_pci_funcs =
{
.card_present = NULL,
.cor_sreset = prism2_pci_cor_sreset,
+ .dev_open = NULL,
+ .dev_close = NULL,
.genesis_reset = prism2_pci_genesis_reset,
.hw_type = HOSTAP_HW_PCI,
};
@@ -358,6 +352,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
return hostap_hw_ready(dev);
fail:
+ kfree(hw_priv);
+
if (irq_registered && dev)
free_irq(dev->irq, dev);
@@ -368,8 +364,10 @@ static int prism2_pci_probe(struct pci_dev *pdev,
err_out_disable:
pci_disable_device(pdev);
- prism2_free_local_data(dev);
kfree(hw_priv);
+ if (local)
+ local->hw_priv = NULL;
+ prism2_free_local_data(dev);
return -ENODEV;
}
@@ -394,8 +392,9 @@ static void prism2_pci_remove(struct pci_dev *pdev)
free_irq(dev->irq, dev);
mem_start = hw_priv->mem_start;
- prism2_free_local_data(dev);
kfree(hw_priv);
+ iface->local->hw_priv = NULL;
+ prism2_free_local_data(dev);
iounmap(mem_start);
@@ -442,7 +441,7 @@ static int prism2_pci_resume(struct pci_dev *pdev)
MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
static struct pci_driver prism2_pci_drv_id = {
- .name = "hostap_pci",
+ .name = "prism2_pci",
.id_table = prism2_pci_id_table,
.probe = prism2_pci_probe,
.remove = prism2_pci_remove,
diff --git a/trunk/drivers/net/wireless/hostap/hostap_plx.c b/trunk/drivers/net/wireless/hostap/hostap_plx.c
index 78d67b408b2f..474ef83d813e 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_plx.c
+++ b/trunk/drivers/net/wireless/hostap/hostap_plx.c
@@ -328,6 +328,8 @@ static struct prism2_helper_functions prism2_plx_funcs =
{
.card_present = NULL,
.cor_sreset = prism2_plx_cor_sreset,
+ .dev_open = NULL,
+ .dev_close = NULL,
.genesis_reset = prism2_plx_genesis_reset,
.hw_type = HOSTAP_HW_PLX,
};
@@ -568,8 +570,10 @@ static int prism2_plx_probe(struct pci_dev *pdev,
return hostap_hw_ready(dev);
fail:
- prism2_free_local_data(dev);
kfree(hw_priv);
+ if (local)
+ local->hw_priv = NULL;
+ prism2_free_local_data(dev);
if (irq_registered && dev)
free_irq(dev->irq, dev);
@@ -602,8 +606,9 @@ static void prism2_plx_remove(struct pci_dev *pdev)
if (dev->irq)
free_irq(dev->irq, dev);
+ kfree(iface->local->hw_priv);
+ iface->local->hw_priv = NULL;
prism2_free_local_data(dev);
- kfree(hw_priv);
pci_disable_device(pdev);
}
@@ -611,7 +616,7 @@ static void prism2_plx_remove(struct pci_dev *pdev)
MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
static struct pci_driver prism2_plx_drv_id = {
- .name = "hostap_plx",
+ .name = "prism2_plx",
.id_table = prism2_plx_id_table,
.probe = prism2_plx_probe,
.remove = prism2_plx_remove,
diff --git a/trunk/drivers/net/wireless/hostap/hostap_wlan.h b/trunk/drivers/net/wireless/hostap/hostap_wlan.h
index cfd801559492..cc061e1560d3 100644
--- a/trunk/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/trunk/drivers/net/wireless/hostap/hostap_wlan.h
@@ -552,6 +552,8 @@ struct prism2_helper_functions {
* (hostap_{cs,plx,pci}.c */
int (*card_present)(local_info_t *local);
void (*cor_sreset)(local_info_t *local);
+ int (*dev_open)(local_info_t *local);
+ int (*dev_close)(local_info_t *local);
void (*genesis_reset)(local_info_t *local, int hcr);
/* the following functions are from hostap_hw.c, but they may have some
diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c
index ad7f8cd76db9..2414e6493aa5 100644
--- a/trunk/drivers/net/wireless/ipw2100.c
+++ b/trunk/drivers/net/wireless/ipw2100.c
@@ -800,7 +800,8 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv,
* doesn't seem to have as many firmware restart cycles...
*
* As a test, we're sticking in a 1/100s delay here */
- schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ / 100);
return 0;
@@ -1255,7 +1256,8 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv)
IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
i = 5000;
do {
- schedule_timeout_uninterruptible(msecs_to_jiffies(40));
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(40 * HZ / 1000);
/* Todo... wait for sync command ... */
read_register(priv->net_dev, IPW_REG_INTA, &inta);
@@ -1409,7 +1411,8 @@ static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
(val2 & IPW2100_COMMAND_PHY_OFF))
return 0;
- schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
}
return -EIO;
@@ -1463,7 +1466,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
{
-#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
+#define HW_POWER_DOWN_DELAY (HZ / 10)
struct host_command cmd = {
.host_command = HOST_PRE_POWER_DOWN,
@@ -1517,8 +1520,10 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
printk(KERN_WARNING DRV_NAME ": "
"%s: Power down command failed: Error %d\n",
priv->net_dev->name, err);
- else
- schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
+ else {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HW_POWER_DOWN_DELAY);
+ }
}
priv->status &= ~STATUS_ENABLED;
@@ -2948,7 +2953,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
int next = txq->next;
int i = 0;
struct ipw2100_data_header *ipw_hdr;
- struct ieee80211_hdr_3addr *hdr;
+ struct ieee80211_hdr *hdr;
while (!list_empty(&priv->tx_pend_list)) {
/* if there isn't enough space in TBD queue, then
@@ -2984,7 +2989,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
packet->index = txq->next;
ipw_hdr = packet->info.d_struct.data;
- hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
+ hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
fragments[0]->data;
if (priv->ieee->iw_mode == IW_MODE_INFRA) {
@@ -3269,8 +3274,7 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data,
return IRQ_NONE;
}
-static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
- int pri)
+static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
{
struct ipw2100_priv *priv = ieee80211_priv(dev);
struct list_head *element;
diff --git a/trunk/drivers/net/wireless/ipw2100.h b/trunk/drivers/net/wireless/ipw2100.h
index c9e99ce15d66..2a3cdbd50168 100644
--- a/trunk/drivers/net/wireless/ipw2100.h
+++ b/trunk/drivers/net/wireless/ipw2100.h
@@ -808,7 +808,7 @@ struct ipw2100_priv {
struct ipw2100_rx {
union {
unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
u32 status;
struct ipw2100_notification notification;
struct ipw2100_cmd_header command;
diff --git a/trunk/drivers/net/wireless/ipw2200.c b/trunk/drivers/net/wireless/ipw2200.c
index de4e6c23e4b8..b7f275c00de3 100644
--- a/trunk/drivers/net/wireless/ipw2200.c
+++ b/trunk/drivers/net/wireless/ipw2200.c
@@ -4904,7 +4904,7 @@ static void ipw_rx(struct ipw_priv *priv)
{
struct ipw_rx_mem_buffer *rxb;
struct ipw_rx_packet *pkt;
- struct ieee80211_hdr_4addr *header;
+ struct ieee80211_hdr *header;
u32 r, w, i;
u8 network_packet;
@@ -4967,9 +4967,8 @@ static void ipw_rx(struct ipw_priv *priv)
#endif
header =
- (struct ieee80211_hdr_4addr *)(rxb->skb->
- data +
- IPW_RX_FRAME_SIZE);
+ (struct ieee80211_hdr *)(rxb->skb->data +
+ IPW_RX_FRAME_SIZE);
/* TODO: Check Ad-Hoc dest/source and make sure
* that we are actually parsing these packets
* correctly -- we should probably use the
@@ -5318,6 +5317,8 @@ static int ipw_wx_set_freq(struct net_device *dev,
IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
return ipw_set_channel(priv, (u8) fwrq->m);
+
+ return 0;
}
static int ipw_wx_get_freq(struct net_device *dev,
@@ -6009,12 +6010,12 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
}
if (priv->adapter == IPW_2915ABG) {
- priv->ieee->abg_true = 1;
+ priv->ieee->abg_ture = 1;
if (mode & IEEE_A) {
band |= IEEE80211_52GHZ_BAND;
modulation |= IEEE80211_OFDM_MODULATION;
} else
- priv->ieee->abg_true = 0;
+ priv->ieee->abg_ture = 0;
} else {
if (mode & IEEE_A) {
IPW_WARNING("Attempt to set 2200BG into "
@@ -6022,20 +6023,20 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
return -EINVAL;
}
- priv->ieee->abg_true = 0;
+ priv->ieee->abg_ture = 0;
}
if (mode & IEEE_B) {
band |= IEEE80211_24GHZ_BAND;
modulation |= IEEE80211_CCK_MODULATION;
} else
- priv->ieee->abg_true = 0;
+ priv->ieee->abg_ture = 0;
if (mode & IEEE_G) {
band |= IEEE80211_24GHZ_BAND;
modulation |= IEEE80211_OFDM_MODULATION;
} else
- priv->ieee->abg_true = 0;
+ priv->ieee->abg_ture = 0;
priv->ieee->mode = mode;
priv->ieee->freq_band = band;
@@ -6324,7 +6325,7 @@ we need to heavily modify the ieee80211_skb_to_txb.
static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
{
- struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
txb->fragments[0]->data;
int i = 0;
struct tfd_frame *tfd;
@@ -6447,7 +6448,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
}
static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
- struct net_device *dev, int pri)
+ struct net_device *dev)
{
struct ipw_priv *priv = ieee80211_priv(dev);
unsigned long flags;
@@ -7107,7 +7108,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO DRV_NAME
": Detected Intel PRO/Wireless 2915ABG Network "
"Connection\n");
- priv->ieee->abg_true = 1;
+ priv->ieee->abg_ture = 1;
band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
@@ -7123,7 +7124,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
": Detected Intel PRO/Wireless 2200BG Network "
"Connection\n");
- priv->ieee->abg_true = 0;
+ priv->ieee->abg_ture = 0;
band = IEEE80211_24GHZ_BAND;
modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
diff --git a/trunk/drivers/net/wireless/ipw2200.h b/trunk/drivers/net/wireless/ipw2200.h
index e9cf32bf3e31..5b00882133f9 100644
--- a/trunk/drivers/net/wireless/ipw2200.h
+++ b/trunk/drivers/net/wireless/ipw2200.h
@@ -1654,12 +1654,12 @@ static const long ipw_frequencies[] = {
#define IPW_MAX_CONFIG_RETRIES 10
-static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
+static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
{
u32 retval;
u16 fc;
- retval = sizeof(struct ieee80211_hdr_3addr);
+ retval = sizeof(struct ieee80211_hdr);
fc = le16_to_cpu(hdr->frame_ctl);
/*
diff --git a/trunk/drivers/net/wireless/netwave_cs.c b/trunk/drivers/net/wireless/netwave_cs.c
index 92793b958e32..ca6c03c89926 100644
--- a/trunk/drivers/net/wireless/netwave_cs.c
+++ b/trunk/drivers/net/wireless/netwave_cs.c
@@ -57,7 +57,9 @@
#include
#ifdef CONFIG_NET_RADIO
#include
+#if WIRELESS_EXT > 12
#include
+#endif /* WIRELESS_EXT > 12 */
#endif
#include
@@ -223,7 +225,10 @@ static void update_stats(struct net_device *dev);
static struct net_device_stats *netwave_get_stats(struct net_device *dev);
/* Wireless extensions */
+#ifdef WIRELESS_EXT
static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
+#endif
+static int netwave_ioctl(struct net_device *, struct ifreq *, int);
static void set_multicast_list(struct net_device *dev);
@@ -255,7 +260,26 @@ static dev_link_t *dev_list;
because they generally can't be allocated dynamically.
*/
+#if WIRELESS_EXT <= 12
+/* Wireless extensions backward compatibility */
+
+/* Part of iw_handler prototype we need */
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+
+/* Wireless Extension Backward compatibility - Jean II
+ * If the new wireless device private ioctl range is not defined,
+ * default to standard device private ioctl range */
+#ifndef SIOCIWFIRSTPRIV
+#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
+#endif /* SIOCIWFIRSTPRIV */
+
+#else /* WIRELESS_EXT <= 12 */
static const struct iw_handler_def netwave_handler_def;
+#endif /* WIRELESS_EXT <= 12 */
#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1 /* Site Survey Snapshot */
@@ -295,7 +319,9 @@ typedef struct netwave_private {
struct timer_list watchdog; /* To avoid blocking state */
struct site_survey nss;
struct net_device_stats stats;
+#ifdef WIRELESS_EXT
struct iw_statistics iw_stats; /* Wireless stats */
+#endif
} netwave_private;
#ifdef NETWAVE_STATS
@@ -327,6 +353,7 @@ static inline void wait_WOC(unsigned int iobase)
while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ;
}
+#ifdef WIRELESS_EXT
static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
kio_addr_t iobase) {
u_short resultBuffer;
@@ -349,7 +376,9 @@ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
sizeof(struct site_survey));
}
}
+#endif
+#ifdef WIRELESS_EXT
/*
* Function netwave_get_wireless_stats (dev)
*
@@ -382,6 +411,7 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
return &priv->iw_stats;
}
+#endif
/*
* Function netwave_attach (void)
@@ -441,7 +471,13 @@ static dev_link_t *netwave_attach(void)
dev->get_stats = &netwave_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* wireless extensions */
+#if WIRELESS_EXT <= 16
+ dev->get_wireless_stats = &netwave_get_wireless_stats;
+#endif /* WIRELESS_EXT <= 16 */
+#if WIRELESS_EXT > 12
dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
+#endif /* WIRELESS_EXT > 12 */
+ dev->do_ioctl = &netwave_ioctl;
dev->tx_timeout = &netwave_watchdog;
dev->watchdog_timeo = TX_TIMEOUT;
@@ -540,8 +576,13 @@ static int netwave_set_nwid(struct net_device *dev,
/* Disable interrupts & save flags */
spin_lock_irqsave(&priv->spinlock, flags);
+#if WIRELESS_EXT > 8
if(!wrqu->nwid.disabled) {
domain = wrqu->nwid.value;
+#else /* WIRELESS_EXT > 8 */
+ if(wrqu->nwid.on) {
+ domain = wrqu->nwid.nwid;
+#endif /* WIRELESS_EXT > 8 */
printk( KERN_DEBUG "Setting domain to 0x%x%02x\n",
(domain >> 8) & 0x01, domain & 0xff);
wait_WOC(iobase);
@@ -565,9 +606,15 @@ static int netwave_get_nwid(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
+#if WIRELESS_EXT > 8
wrqu->nwid.value = domain;
wrqu->nwid.disabled = 0;
wrqu->nwid.fixed = 1;
+#else /* WIRELESS_EXT > 8 */
+ wrqu->nwid.nwid = domain;
+ wrqu->nwid.on = 1;
+#endif /* WIRELESS_EXT > 8 */
+
return 0;
}
@@ -610,11 +657,17 @@ static int netwave_get_scramble(struct net_device *dev,
{
key[1] = scramble_key & 0xff;
key[0] = (scramble_key>>8) & 0xff;
+#if WIRELESS_EXT > 8
wrqu->encoding.flags = IW_ENCODE_ENABLED;
wrqu->encoding.length = 2;
+#else /* WIRELESS_EXT > 8 */
+ wrqu->encoding.method = 1;
+#endif /* WIRELESS_EXT > 8 */
+
return 0;
}
+#if WIRELESS_EXT > 8
/*
* Wireless Handler : get mode
*/
@@ -630,6 +683,7 @@ static int netwave_get_mode(struct net_device *dev,
return 0;
}
+#endif /* WIRELESS_EXT > 8 */
/*
* Wireless Handler : get range info
@@ -648,9 +702,11 @@ static int netwave_get_range(struct net_device *dev,
/* Set all the info we don't care or don't know about to zero */
memset(range, 0, sizeof(struct iw_range));
+#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = 9; /* Nothing for us in v10 and v11 */
+#endif /* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range->throughput = 450 * 1000; /* don't argue on this ! */
@@ -664,12 +720,16 @@ static int netwave_get_range(struct net_device *dev,
range->max_qual.level = 255;
range->max_qual.noise = 0;
+#if WIRELESS_EXT > 7
range->num_bitrates = 1;
range->bitrate[0] = 1000000; /* 1 Mb/s */
+#endif /* WIRELESS_EXT > 7 */
+#if WIRELESS_EXT > 8
range->encoding_size[0] = 2; /* 16 bits scrambling */
range->num_encoding_sizes = 1;
range->max_encoding_tokens = 1; /* Only one key possible */
+#endif /* WIRELESS_EXT > 8 */
return ret;
}
@@ -715,6 +775,8 @@ static const struct iw_priv_args netwave_private_args[] = {
"getsitesurvey" },
};
+#if WIRELESS_EXT > 12
+
static const iw_handler netwave_handler[] =
{
NULL, /* SIOCSIWNAME */
@@ -777,8 +839,131 @@ static const struct iw_handler_def netwave_handler_def =
.standard = (iw_handler *) netwave_handler,
.private = (iw_handler *) netwave_private_handler,
.private_args = (struct iw_priv_args *) netwave_private_args,
+#if WIRELESS_EXT > 16
.get_wireless_stats = netwave_get_wireless_stats,
+#endif /* WIRELESS_EXT > 16 */
};
+#endif /* WIRELESS_EXT > 12 */
+
+/*
+ * Function netwave_ioctl (dev, rq, cmd)
+ *
+ * Perform ioctl : config & info stuff
+ * This is the stuff that are treated the wireless extensions (iwconfig)
+ *
+ */
+static int netwave_ioctl(struct net_device *dev, /* ioctl device */
+ struct ifreq *rq, /* Data passed */
+ int cmd) /* Ioctl number */
+{
+ int ret = 0;
+#ifdef WIRELESS_EXT
+#if WIRELESS_EXT <= 12
+ struct iwreq *wrq = (struct iwreq *) rq;
+#endif
+#endif
+
+ DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
+
+ /* Look what is the request */
+ switch(cmd) {
+ /* --------------- WIRELESS EXTENSIONS --------------- */
+#ifdef WIRELESS_EXT
+#if WIRELESS_EXT <= 12
+ case SIOCGIWNAME:
+ netwave_get_name(dev, NULL, &(wrq->u), NULL);
+ break;
+ case SIOCSIWNWID:
+ ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
+ break;
+ case SIOCGIWNWID:
+ ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
+ break;
+#if WIRELESS_EXT > 8 /* Note : The API did change... */
+ case SIOCGIWENCODE:
+ /* Get scramble key */
+ if(wrq->u.encoding.pointer != (caddr_t) 0)
+ {
+ char key[2];
+ ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
+ if(copy_to_user(wrq->u.encoding.pointer, key, 2))
+ ret = -EFAULT;
+ }
+ break;
+ case SIOCSIWENCODE:
+ /* Set scramble key */
+ if(wrq->u.encoding.pointer != (caddr_t) 0)
+ {
+ char key[2];
+ if(copy_from_user(key, wrq->u.encoding.pointer, 2))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
+ }
+ break;
+ case SIOCGIWMODE:
+ /* Mode of operation */
+ ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
+ break;
+#else /* WIRELESS_EXT > 8 */
+ case SIOCGIWENCODE:
+ /* Get scramble key */
+ ret = netwave_get_scramble(dev, NULL, &(wrq->u),
+ (char *) &wrq->u.encoding.code);
+ break;
+ case SIOCSIWENCODE:
+ /* Set scramble key */
+ ret = netwave_set_scramble(dev, NULL, &(wrq->u),
+ (char *) &wrq->u.encoding.code);
+ break;
+#endif /* WIRELESS_EXT > 8 */
+ case SIOCGIWRANGE:
+ /* Basic checking... */
+ if(wrq->u.data.pointer != (caddr_t) 0) {
+ struct iw_range range;
+ ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
+ if (copy_to_user(wrq->u.data.pointer, &range,
+ sizeof(struct iw_range)))
+ ret = -EFAULT;
+ }
+ break;
+ case SIOCGIWPRIV:
+ /* Basic checking... */
+ if(wrq->u.data.pointer != (caddr_t) 0) {
+ /* Set the number of ioctl available */
+ wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
+
+ /* Copy structure to the user buffer */
+ if(copy_to_user(wrq->u.data.pointer,
+ (u_char *) netwave_private_args,
+ sizeof(netwave_private_args)))
+ ret = -EFAULT;
+ }
+ break;
+ case SIOCGIPSNAP:
+ if(wrq->u.data.pointer != (caddr_t) 0) {
+ char buffer[sizeof( struct site_survey)];
+ ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
+ /* Copy structure to the user buffer */
+ if(copy_to_user(wrq->u.data.pointer,
+ buffer,
+ sizeof( struct site_survey)))
+ {
+ printk(KERN_DEBUG "Bad buffer!\n");
+ break;
+ }
+ }
+ break;
+#endif /* WIRELESS_EXT <= 12 */
+#endif /* WIRELESS_EXT */
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
/*
* Function netwave_pcmcia_config (link)
diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c
index d3d4ec9e242e..15ceaf615756 100644
--- a/trunk/drivers/net/wireless/orinoco.c
+++ b/trunk/drivers/net/wireless/orinoco.c
@@ -77,16 +77,30 @@
#define DRIVER_NAME "orinoco"
#include
+
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
#include
+#include
#include
#include
#include
#include
#include
+#include
+
+#include
+#include
+#include
+
+#include "hermes.h"
#include "hermes_rid.h"
#include "orinoco.h"
@@ -123,7 +137,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
-#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
+#define SPY_NUMBER(priv) (priv->spy_number)
#else
#define SPY_NUMBER(priv) 0
#endif /* WIRELESS_SPY */
@@ -202,32 +216,31 @@ static struct {
/********************************************************************/
/* Used in Event handling.
- * We avoid nested structures as they break on ARM -- Moustafa */
+ * We avoid nested structres as they break on ARM -- Moustafa */
struct hermes_tx_descriptor_802_11 {
/* hermes_tx_descriptor */
- __le16 status;
- __le16 reserved1;
- __le16 reserved2;
- __le32 sw_support;
+ u16 status;
+ u16 reserved1;
+ u16 reserved2;
+ u32 sw_support;
u8 retry_count;
u8 tx_rate;
- __le16 tx_control;
+ u16 tx_control;
- /* ieee80211_hdr */
- __le16 frame_ctl;
- __le16 duration_id;
+ /* ieee802_11_hdr */
+ u16 frame_ctl;
+ u16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- __le16 seq_ctl;
+ u16 seq_ctl;
u8 addr4[ETH_ALEN];
-
- __le16 data_len;
+ u16 data_len;
/* ethhdr */
- u8 h_dest[ETH_ALEN]; /* destination eth addr */
- u8 h_source[ETH_ALEN]; /* source ether addr */
- __be16 h_proto; /* packet type ID field */
+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
+ unsigned char h_source[ETH_ALEN]; /* source ether addr */
+ unsigned short h_proto; /* packet type ID field */
/* p8022_hdr */
u8 dsap;
@@ -235,31 +248,31 @@ struct hermes_tx_descriptor_802_11 {
u8 ctrl;
u8 oui[3];
- __be16 ethertype;
+ u16 ethertype;
} __attribute__ ((packed));
/* Rx frame header except compatibility 802.3 header */
struct hermes_rx_descriptor {
/* Control */
- __le16 status;
- __le32 time;
+ u16 status;
+ u32 time;
u8 silence;
u8 signal;
u8 rate;
u8 rxflow;
- __le32 reserved;
+ u32 reserved;
/* 802.11 header */
- __le16 frame_ctl;
- __le16 duration_id;
+ u16 frame_ctl;
+ u16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- __le16 seq_ctl;
+ u16 seq_ctl;
u8 addr4[ETH_ALEN];
/* Data length */
- __le16 data_len;
+ u16 data_len;
} __attribute__ ((packed));
/********************************************************************/
@@ -383,14 +396,14 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
/* If a spy address is defined, we report stats of the
* first spy address - Jean II */
if (SPY_NUMBER(priv)) {
- wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
- wstats->qual.level = priv->spy_data.spy_stat[0].level;
- wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
- wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
+ wstats->qual.qual = priv->spy_stat[0].qual;
+ wstats->qual.level = priv->spy_stat[0].level;
+ wstats->qual.noise = priv->spy_stat[0].noise;
+ wstats->qual.updated = priv->spy_stat[0].updated;
}
} else {
struct {
- __le16 qual, signal, noise;
+ u16 qual, signal, noise;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -492,9 +505,11 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
/* Check packet length, pad short packets, round up odd length */
len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
- skb = skb_padto(skb, len);
- if (skb == NULL)
- goto fail;
+ if (skb->len < len) {
+ skb = skb_padto(skb, len);
+ if (skb == NULL)
+ goto fail;
+ }
len -= ETH_HLEN;
eh = (struct ethhdr *)skb->data;
@@ -619,17 +634,16 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
- u16 status;
struct hermes_tx_descriptor_802_11 hdr;
int err = 0;
if (fid == DUMMY_FID)
return; /* Nothing's really happened */
- /* Read part of the frame header - we need status and addr1 */
+ /* Read the frame header */
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
- offsetof(struct hermes_tx_descriptor_802_11,
- addr2),
+ sizeof(struct hermes_tx_descriptor) +
+ sizeof(struct ieee80211_hdr),
fid, 0);
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -649,8 +663,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
* exceeded, because that's the only status that really mean
* that this particular node went away.
* Other errors means that *we* screwed up. - Jean II */
- status = le16_to_cpu(hdr.status);
- if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+ hdr.status = le16_to_cpu(hdr.status);
+ if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
union iwreq_data wrqu;
/* Copy 802.11 dest address.
@@ -709,13 +723,18 @@ static inline int is_ethersnap(void *_hdr)
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
int level, int noise)
{
- struct iw_quality wstats;
- wstats.level = level - 0x95;
- wstats.noise = noise - 0x95;
- wstats.qual = (level > noise) ? (level - noise) : 0;
- wstats.updated = 7;
- /* Update spy records */
- wireless_spy_update(dev, mac, &wstats);
+ struct orinoco_private *priv = netdev_priv(dev);
+ int i;
+
+ /* Gather wireless spy statistics: for each packet, compare the
+ * source address with out list, and if match, get the stats... */
+ for (i = 0; i < priv->spy_number; i++)
+ if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
+ priv->spy_stat[i].level = level - 0x95;
+ priv->spy_stat[i].noise = noise - 0x95;
+ priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
+ priv->spy_stat[i].updated = 7;
+ }
}
static void orinoco_stat_gather(struct net_device *dev,
@@ -1036,7 +1055,7 @@ static void orinoco_join_ap(struct net_device *dev)
unsigned long flags;
struct join_req {
u8 bssid[ETH_ALEN];
- __le16 channel;
+ u16 channel;
} __attribute__ ((packed)) req;
const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
struct prism2_scan_apinfo *atom = NULL;
@@ -1051,7 +1070,7 @@ static void orinoco_join_ap(struct net_device *dev)
return;
if (orinoco_lock(priv, &flags) != 0)
- goto fail_lock;
+ goto out;
/* Sanity checks in case user changed something in the meantime */
if (! priv->bssid_fixed)
@@ -1096,10 +1115,8 @@ static void orinoco_join_ap(struct net_device *dev)
printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
out:
- orinoco_unlock(priv, &flags);
-
- fail_lock:
kfree(buf);
+ orinoco_unlock(priv, &flags);
}
/* Send new BSSID to userspace */
@@ -1117,14 +1134,12 @@ static void orinoco_send_wevents(struct net_device *dev)
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
if (err != 0)
- goto out;
+ return;
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/* Send event to user space */
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-
- out:
orinoco_unlock(priv, &flags);
}
@@ -1133,8 +1148,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
u16 infofid;
struct {
- __le16 len;
- __le16 type;
+ u16 len;
+ u16 type;
} __attribute__ ((packed)) info;
int len, type;
int err;
@@ -2449,10 +2464,6 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->get_stats = orinoco_get_stats;
dev->ethtool_ops = &orinoco_ethtool_ops;
dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
-#ifdef WIRELESS_SPY
- priv->wireless_data.spy_data = &priv->spy_data;
- dev->wireless_data = &priv->wireless_data;
-#endif
dev->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list;
/* we use the default eth_mac_addr for setting the MAC addr */
@@ -2824,7 +2835,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
}
}
- if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
+ if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
/* Quality stats meaningless in ad-hoc mode */
} else {
range->max_qual.qual = 0x8b - 0x2f;
@@ -2871,14 +2882,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
range->min_r_time = 0;
range->max_r_time = 65535 * 1000; /* ??? */
- /* Event capability (kernel) */
- IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
- /* Event capability (driver) */
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
- IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
-
TRACE_EXIT(dev->name);
return 0;
@@ -3838,6 +3841,92 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
return err;
}
+/* Spy is used for link quality/strength measurements in Ad-Hoc mode
+ * Jean II */
+static int orinoco_ioctl_setspy(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *srq,
+ char *extra)
+
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct sockaddr *address = (struct sockaddr *) extra;
+ int number = srq->length;
+ int i;
+ unsigned long flags;
+
+ /* Make sure nobody mess with the structure while we do */
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ /* orinoco_lock() doesn't disable interrupts, so make sure the
+ * interrupt rx path don't get confused while we copy */
+ priv->spy_number = 0;
+
+ if (number > 0) {
+ /* Extract the addresses */
+ for (i = 0; i < number; i++)
+ memcpy(priv->spy_address[i], address[i].sa_data,
+ ETH_ALEN);
+ /* Reset stats */
+ memset(priv->spy_stat, 0,
+ sizeof(struct iw_quality) * IW_MAX_SPY);
+ /* Set number of addresses */
+ priv->spy_number = number;
+ }
+
+ /* Now, let the others play */
+ orinoco_unlock(priv, &flags);
+
+ /* Do NOT call commit handler */
+ return 0;
+}
+
+static int orinoco_ioctl_getspy(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *srq,
+ char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct sockaddr *address = (struct sockaddr *) extra;
+ int number;
+ int i;
+ unsigned long flags;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ number = priv->spy_number;
+ /* Create address struct */
+ for (i = 0; i < number; i++) {
+ memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
+ address[i].sa_family = AF_UNIX;
+ }
+ if (number > 0) {
+ /* Create address struct */
+ for (i = 0; i < number; i++) {
+ memcpy(address[i].sa_data, priv->spy_address[i],
+ ETH_ALEN);
+ address[i].sa_family = AF_UNIX;
+ }
+ /* Copy stats */
+ /* In theory, we should disable irqs while copying the stats
+ * because the rx path might update it in the middle...
+ * Bah, who care ? - Jean II */
+ memcpy(extra + (sizeof(struct sockaddr) * number),
+ priv->spy_stat, sizeof(struct iw_quality) * number);
+ }
+ /* Reset updated flags. */
+ for (i = 0; i < number; i++)
+ priv->spy_stat[i].updated = 0;
+
+ orinoco_unlock(priv, &flags);
+
+ srq->length = number;
+
+ return 0;
+}
+
/* Trigger a scan (look for other cells in the vicinity */
static int orinoco_ioctl_setscan(struct net_device *dev,
struct iw_request_info *info,
@@ -3910,7 +3999,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
HERMES_HOSTSCAN_SYMBOL_BCAST);
break;
case FIRMWARE_TYPE_INTERSIL: {
- __le16 req[3];
+ u16 req[3];
req[0] = cpu_to_le16(0x3fff); /* All channels */
req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
@@ -3984,7 +4073,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
case FIRMWARE_TYPE_INTERSIL:
offset = 4;
if (priv->has_hostscan) {
- atom_len = le16_to_cpup((__le16 *)scan);
+ atom_len = le16_to_cpup((u16 *)scan);
/* Sanity check for atom_len */
if (atom_len < sizeof(struct prism2_scan_apinfo)) {
printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
@@ -4268,10 +4357,8 @@ static const iw_handler orinoco_handler[] = {
[SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
[SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
- [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
- [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
- [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
- [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
+ [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
+ [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
[SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
[SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
[SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
diff --git a/trunk/drivers/net/wireless/orinoco.h b/trunk/drivers/net/wireless/orinoco.h
index 7a17bb31fc89..2f213a7103fe 100644
--- a/trunk/drivers/net/wireless/orinoco.h
+++ b/trunk/drivers/net/wireless/orinoco.h
@@ -7,11 +7,12 @@
#ifndef _ORINOCO_H
#define _ORINOCO_H
-#define DRIVER_VERSION "0.15rc3"
+#define DRIVER_VERSION "0.15rc2"
+#include
+#include
#include
#include
-#include
#include
#include "hermes.h"
@@ -27,7 +28,7 @@
#define ORINOCO_MAX_KEYS 4
struct orinoco_key {
- __le16 len; /* always stored as little-endian */
+ u16 len; /* always stored as little-endian */
char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed));
@@ -35,14 +36,14 @@ struct header_struct {
/* 802.3 */
u8 dest[ETH_ALEN];
u8 src[ETH_ALEN];
- __be16 len;
+ u16 len;
/* 802.2 */
u8 dsap;
u8 ssap;
u8 ctrl;
/* SNAP */
u8 oui[3];
- unsigned short ethertype;
+ u16 ethertype;
} __attribute__ ((packed));
typedef enum {
@@ -111,8 +112,9 @@ struct orinoco_private {
u16 pm_on, pm_mcast, pm_period, pm_timeout;
u16 preamble;
#ifdef WIRELESS_SPY
- struct iw_spy_data spy_data; /* iwspy support */
- struct iw_public_data wireless_data;
+ int spy_number;
+ u_char spy_address[IW_MAX_SPY][ETH_ALEN];
+ struct iw_quality spy_stat[IW_MAX_SPY];
#endif
/* Configuration dependent variables */
diff --git a/trunk/drivers/net/wireless/orinoco_cs.c b/trunk/drivers/net/wireless/orinoco_cs.c
index dc1128a00971..bedd7f9f23e4 100644
--- a/trunk/drivers/net/wireless/orinoco_cs.c
+++ b/trunk/drivers/net/wireless/orinoco_cs.c
@@ -14,16 +14,33 @@
#define PFX DRIVER_NAME ": "
#include
+#ifdef __IN_PCMCIA_PACKAGE__
+#include
+#endif /* __IN_PCMCIA_PACKAGE__ */
+
#include
#include
#include
-#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include
#include
#include
#include
#include
+#include