drivers/net/ethernet/smsc/smsc911x.c
Source file repositories/reference/linux-study-clean/drivers/net/ethernet/smsc/smsc911x.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ethernet/smsc/smsc911x.c- Extension
.c- Size
- 71206 bytes
- Lines
- 2703
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/crc32.hlinux/clk.hlinux/delay.hlinux/errno.hlinux/etherdevice.hlinux/ethtool.hlinux/init.hlinux/interrupt.hlinux/ioport.hlinux/kernel.hlinux/module.hlinux/netdevice.hlinux/platform_device.hlinux/regulator/consumer.hlinux/sched.hlinux/timer.hlinux/bug.hlinux/bitops.hlinux/irq.hlinux/io.hlinux/swab.hlinux/phy.hlinux/smsc911x.hlinux/device.hlinux/of.hlinux/of_net.hlinux/acpi.hlinux/pm_runtime.hlinux/property.hlinux/gpio/consumer.hsmsc911x.h
Detected Declarations
struct smsc911x_datastruct smsc911x_opsstruct smsc911x_datafunction __smsc911x_reg_readfunction __smsc911x_reg_read_shiftfunction smsc911x_reg_readfunction __smsc911x_reg_writefunction __smsc911x_reg_write_shiftfunction smsc911x_reg_writefunction smsc911x_tx_writefifofunction smsc911x_tx_writefifo_shiftfunction smsc911x_rx_readfifofunction smsc911x_rx_readfifo_shiftfunction smsc911x_enable_resourcesfunction smsc911x_disable_resourcesfunction smsc911x_request_resourcesfunction smsc911x_free_resourcesfunction smsc911x_mac_completefunction smsc911x_mac_readfunction smsc911x_mac_writefunction smsc911x_mii_readfunction smsc911x_mii_writefunction smsc911x_phy_enable_externalfunction smsc911x_phy_initialise_externalfunction smsc911x_tx_get_txstatusfunction smsc911x_rx_get_rxstatusfunction smsc911x_phy_check_loopbackpktfunction smsc911x_phy_resetfunction smsc911x_phy_loopbacktestfunction smsc911x_phy_update_flowcontrolfunction smsc911x_phy_adjust_linkfunction smsc911x_mii_probefunction smsc911x_mii_initfunction smsc911x_tx_get_txstatcountfunction smsc911x_tx_update_txcountersfunction smsc911x_rx_counterrorsfunction smsc911x_rx_fastforwardfunction smsc911x_pollfunction smsc911x_hashfunction smsc911x_rx_multicast_updatefunction smsc911x_rx_multicast_update_workaroundfunction smsc911x_phy_general_power_upfunction smsc911x_phy_disable_energy_detectfunction smsc911x_phy_enable_energy_detectfunction smsc911x_soft_resetfunction smsc911x_set_hw_mac_addressfunction smsc911x_disable_irq_chipfunction smsc911x_irqhandler
Annotated Snippet
static const struct net_device_ops smsc911x_netdev_ops = {
.ndo_open = smsc911x_open,
.ndo_stop = smsc911x_stop,
.ndo_start_xmit = smsc911x_hard_start_xmit,
.ndo_get_stats = smsc911x_get_stats,
.ndo_set_rx_mode = smsc911x_set_multicast_list,
.ndo_eth_ioctl = phy_do_ioctl_running,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = smsc911x_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = smsc911x_poll_controller,
#endif
};
/* copies the current mac address from hardware to dev->dev_addr */
static void smsc911x_read_mac_address(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
u32 mac_high16, mac_low32;
u8 addr[ETH_ALEN];
mac_high16 = smsc911x_mac_read(pdata, ADDRH);
mac_low32 = smsc911x_mac_read(pdata, ADDRL);
/* The first mac_read in some setups can incorrectly read 0. Re-read it
* to get the full MAC if this is observed.
*/
if (mac_high16 == 0) {
SMSC_TRACE(pdata, probe, "Re-read MAC ADDRH\n");
mac_high16 = smsc911x_mac_read(pdata, ADDRH);
}
addr[0] = (u8)(mac_low32);
addr[1] = (u8)(mac_low32 >> 8);
addr[2] = (u8)(mac_low32 >> 16);
addr[3] = (u8)(mac_low32 >> 24);
addr[4] = (u8)(mac_high16);
addr[5] = (u8)(mac_high16 >> 8);
eth_hw_addr_set(dev, addr);
}
/* Initializing private device structures, only called from probe */
static int smsc911x_init(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
unsigned int byte_test, mask;
unsigned int to = 100;
SMSC_TRACE(pdata, probe, "Driver Parameters:");
SMSC_TRACE(pdata, probe, "LAN base: 0x%08lX",
(unsigned long)pdata->ioaddr);
SMSC_TRACE(pdata, probe, "IRQ: %d", dev->irq);
SMSC_TRACE(pdata, probe, "PHY will be autodetected.");
spin_lock_init(&pdata->dev_lock);
spin_lock_init(&pdata->mac_lock);
if (pdata->ioaddr == NULL) {
SMSC_WARN(pdata, probe, "pdata->ioaddr: 0x00000000");
return -ENODEV;
}
/*
* poll the READY bit in PMT_CTRL. Any other access to the device is
* forbidden while this bit isn't set. Try for 100ms
*
* Note that this test is done before the WORD_SWAP register is
* programmed. So in some configurations the READY bit is at 16 before
* WORD_SWAP is written to. This issue is worked around by waiting
* until either bit 0 or bit 16 gets set in PMT_CTRL.
*
* SMSC has confirmed that checking bit 16 (marked as reserved in
* the datasheet) is fine since these bits "will either never be set
* or can only go high after READY does (so also indicate the device
* is ready)".
*/
mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
udelay(1000);
if (to == 0) {
netdev_err(dev, "Device not READY in 100ms aborting\n");
return -ENODEV;
}
/* Check byte ordering */
byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
SMSC_TRACE(pdata, probe, "BYTE_TEST: 0x%08X", byte_test);
if (byte_test == 0x43218765) {
Annotation
- Immediate include surface: `linux/crc32.h`, `linux/clk.h`, `linux/delay.h`, `linux/errno.h`, `linux/etherdevice.h`, `linux/ethtool.h`, `linux/init.h`, `linux/interrupt.h`.
- Detected declarations: `struct smsc911x_data`, `struct smsc911x_ops`, `struct smsc911x_data`, `function __smsc911x_reg_read`, `function __smsc911x_reg_read_shift`, `function smsc911x_reg_read`, `function __smsc911x_reg_write`, `function __smsc911x_reg_write_shift`, `function smsc911x_reg_write`, `function smsc911x_tx_writefifo`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.