ath9k Driver Registration Process

Source: Internet
Author: User

http://blog.csdn.net/ussam/article/details/24393267

The ath9k NIC driver is used here, the hardware platform is Tp-link tl-wr841n V7.1 Router 1 ath_pci_init ()
The main entrance of the drive is Ath_pci_init () (in the Pci.c file under the linux-3.3.8/drivers/net/wireless/ath/ath9k folder):

int ath_pci_init (void)
{
	return pci_register_driver (&ath_pci_driver);
}
You can see that Ath_pci_driver is passed as a parameter to Pci_register_driver (). The ath_pci_driver is defined as follows (in the Pci.c file under the linux-3.3.8/drivers/net/wireless/ath/ath9k folder):
static struct Pci_driver Ath_pci_driver = {
	. Name       = "ath9k",
	. Id_table   = ath_pci_id_table,
	. Probe      = Ath_pci_probe,
	. Remove     = Ath_pci_remove,
	. driver.pm  = Ath9k_pm_ops,
};
2 Ath_pci_probe ()
Immediately thereafter, the Ath_pci_probe function is called with the probe pointer (the ATH_PCI_PROBE function is defined in the Pci.c file under the linux-3.3.8/drivers/net/wireless/ath/ath9k folder).
static int ath_pci_probe (struct pci_dev *pdev, const struct pci_device_id *id) {... hw = ieee80211_alloc_hw (sizeof (struct
	ATH_SOFTC), &ath9k_ops);
		if (!HW) {Dev_err (&pdev->dev, "No Memory for Ieee80211_hw\n");
		ret =-enomem;
	Goto ERR_ALLOC_HW;
	} set_ieee80211_dev (HW, &pdev->dev);


	Pci_set_drvdata (Pdev, HW);
	sc = hw->priv;
	SC->HW = HW;
	Sc->dev = &pdev->dev;
	Sc->mem = mem;
	/* 'll be cleared in Ath9k_start () */Sc->sc_flags |= sc_op_invalid;
	ret = REQUEST_IRQ (PDEV->IRQ, ATH_ISR, irqf_shared, "ath9k", SC);
		if (ret) {Dev_err (&pdev->dev, "Request_irq failed\n");
	Goto ERR_IRQ;
	} SC->IRQ = pdev->irq;
	ret = Ath9k_init_device (Id->device, SC, &ath_pci_bus_ops);
		if (ret) {Dev_err (&pdev->dev, "Failed to initialize device\n");
	Goto Err_init; } ... }
3 IEEE80211_ALLOC_HW ()
Note This line of code in the body of the Ath_pci_probe () function:
HW = IEEE80211_ALLOC_HW (sizeof (struct ATH_SOFTC), &ath9k_ops);
The function ieee80211_alloc_hw () is defined in the OpenWrt Kernel folder directory/net/mac80211, file main.c, where the parameters passed in are struct ath9k_ops, the structure is defined as follows (in linux-3.3.8/ In the Main.c file under the drivers/net/wireless/ath/ath9k folder):
struct Ieee80211_ops ath9k_ops = {. tx = Ath9k_tx,. Start = Ath9k_start,. Stop = Ath9k_stop,. add_in Terface = Ath9k_add_interface,. change_interface = Ath9k_change_interface,. Remove_interface = Ath9k_remove_int Erface,. config = Ath9k_config,. Configure_filter = Ath9k_configure_filter,. Sta_add = Ath9k_sta_add,. Sta_    remove = Ath9k_sta_remove,. sta_notify = Ath9k_sta_notify,. Conf_tx = Ath9k_conf_tx,. bss_info_changed = Ath9k_bss_info_changed,. Set_key = Ath9k_set_key,. GET_TSF = ATH9K_GET_TSF,. SET_TSF = Ath9k_ SET_TSF,. RESET_TSF = ATH9K_RESET_TSF,. ampdu_action = Ath9k_ampdu_action,. Get_survey = Ath9k_get_surve Y,. rfkill_poll = Ath9k_rfkill_poll_state,. Set_coverage_class = Ath9k_set_coverage_class,. Flush = Ath9k_f Lush,. tx_frames_pending = ath9k_tx_frames_pending,. Tx_last_beacon = Ath9k_tx_last_beacon,. get_stats = ath9k _get_stats,. Set_antennA = Ath9k_set_antenna,. Get_antenna = Ath9k_get_antenna,}; 
After the parameter ath9k_ops is transferred to the IEEE80211_ALLOC_HW () function, the system will be able to use the function pointer defined in the parameter ath9k_ops. In the case of TX, the function pointer will be used in tx.c.
Here's another look at the IEEE80211_ALLOC_HW () function:
struct IEEE80211_HW *ieee80211_alloc_hw (size_t priv_data_len, const struct ieee80211_ops *ops) {struct ieee80211_local *
	Local
	int priv_size, I;
	struct wiphy *wiphy;
BOOL Use_chanctx;
	 .../* Ensure 32-byte alignment of our private data and HW private data.  * We Use the Wiphy priv data for both our ieee80211_local and for * The driver's private data * * in memory it ' ll be Like this: * * +-------------------------+ * |
	 struct Wiphy | * +-------------------------+
	 * |
	 struct Ieee80211_local | * +-------------------------+
	 * |
	 Driver ' s private Data |
* +-------------------------+ * */priv_size = ALIGN (sizeof (*local), netdev_align) + Priv_data_len; Note that here Mac80211_config_ops//With the scan member as an example, the scan will trigger the corresponding function Ieee80211_scan () wiphy = Wiphy_new (&mac80211_config_ OPS, priv_size);
Notice here that the Mac80211_config_ops if (!wiphy) return is NULL;
	...//The local->ops here becomes the passed in parameter ath9k_ops local->ops = OPS; ...//This Task Force column is very important, SW scan case will schedule this task queue to do scan init_dElayed_work (&local->scan_work, ieee80211_scan_work); ...//This tasklet is closely related to receiving data and will be referred to Tasklet_init (&local->tasklet, Ieee80211_tasklet_handler, unsigned lon
	g) local);
... return &local->hw; } export_symbol (IEEE80211_ALLOC_HW);
4 Ath9k_init_device ()
In the function body of ath_pci_probe (), the other important code after the completion of IEEE80211_ALLOC_HW () is:
ret = Ath9k_init_device (Id->device, SC, &ath_pci_bus_ops);
Then analyze Ath9k_init_device () (located in the OpenWrt Kernel folder directory/net/mac80211, file init.c) to observe the initialization process of the device.
int Ath9k_init_device (U16 devid, struct ATH_SOFTC *sc, const struct ath_bus_ops *bus_ops) {struct IEEE80211_HW *HW = sc-
	>hw;
	struct Ath_common *common;
	struct ATH_HW *ah;
	int error = 0;
	struct Ath_regulatory *reg;
	/* Bring up device */error = ATH9K_INIT_SOFTC (Devid, SC, bus_ops);
	if (Error! = 0) goto Error_init;
	Ah = sc->sc_ah;
	Common = Ath9k_hw_common (AH);
	Ath9k_set_hw_capab (SC, HW); /* Initialize Regulatory * * error = Ath_regd_init (&common->regulatory, Sc->hw->wiphy, Ath9k_reg_not
	Ifier);
	if (error) goto ERROR_REGD;
	Reg = &common->regulatory;
	/* Setup TX DMA */error = Ath_tx_init (SC, ath_txbuf);
	if (Error! = 0) goto Error_tx;
	/* Setup RX DMA */error = Ath_rx_init (SC, ath_rxbuf);
	if (Error! = 0) goto Error_rx;
Ath9k_init_txpower_limits (SC);
	... error = IEEE80211_REGISTER_HW (HW);
	if (error) goto Error_register;
	Error = Ath9k_init_debug (AH);
		if (Error) {Ath_err (Common, "unable to create Debugfs files\n"); GotoError_world; } ... }
4.1 First Initialize SOFTC
static int ATH9K_INIT_SOFTC (U16 devid, struct ATH_SOFTC *sc,
			    const struct Ath_bus_ops *bus_ops)
{
...
	Tasklet_init (&SC->INTR_TQ, Ath9k_tasklet, (unsigned long) SC);
	Tasklet_init (&sc->bcon_tasklet, Ath_beacon_tasklet,
		     (unsigned long) SC);
   ...
}
The Tasklet (including the Beacon Frame's Tasklet) is initialized during this process
4.2 Initializing the data transmit/receive memory access
/* Setup TX DMA *
	/error = Ath_tx_init (SC, ath_txbuf);
	if (Error! = 0)
		goto error_tx;
	/* Setup RX DMA *
	/error = Ath_rx_init (SC, ath_rxbuf);
	if (Error! = 0)
		goto ERROR_RX;
4.3 Registering the device
Error = IEEE80211_REGISTER_HW (HW);
At this point, the device starts and the driver is successfully loaded onto the device.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.