Search Linux Wireless

Re: [PATCH v3 11/12] wifi: rtlwifi: Add rtl8192du/sw.{c,h}

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 01/04/2024 04:21, Ping-Ke Shih wrote:
>>
>> I asked linux-usb and they said the two interfaces are probed
>> and disconnected one at a time, so it should be fine without
>> another mutex:
>>
>> https://lore.kernel.org/linux-usb/2024032907-smokeless-imperial-f3f9@gregkh/
> 
> Thanks for the clarification. Then, will you dynamically allocate mutex
> by first interface with ref_cnt=1, and second interface obtains mutex from
> first interface and increases ref_cnt=2?
> 
> When USB disconnection, decrease ref_cnt and if ref_cnt==0 free the mutex 
> no matter which one disconnect first. 
> 
> My thinking above is the same as yours?
> 

I did not consider using a ref_cnt variable. I made the first
probe allocate the things and the first disconnect frees them:


static struct usb_interface *rtl92du_get_other_intf(struct ieee80211_hw *hw)
{
	struct usb_interface *intf;
	struct usb_device *udev;
	u8 other_interfaceindex;

	/* See SET_IEEE80211_DEV(hw, &intf->dev); in usb.c */
	intf = container_of_const(wiphy_dev(hw->wiphy), struct usb_interface, dev);

	other_interfaceindex = 1 - intf->altsetting[0].desc.bInterfaceNumber;

	udev = interface_to_usbdev(intf);

	return usb_ifnum_to_if(udev, other_interfaceindex);
}

static int rtl92du_init_shared_data(struct ieee80211_hw *hw)
{
	struct usb_interface *other_intf = rtl92du_get_other_intf(hw);
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_priv *other_rtlpriv = NULL;
	struct ieee80211_hw *other_hw = NULL;

	if (other_intf)
		other_hw = usb_get_intfdata(other_intf);

	if (other_hw) {
		/* The other interface was already probed. */
		other_rtlpriv = rtl_priv(other_hw);
		rtlpriv->curveindex_2g = other_rtlpriv->curveindex_2g;
		rtlpriv->curveindex_5g = other_rtlpriv->curveindex_5g;
		rtlpriv->mutex_for_power_on_off = other_rtlpriv->mutex_for_power_on_off;
		rtlpriv->mutex_for_hw_init = other_rtlpriv->mutex_for_hw_init;

		if (!rtlpriv->curveindex_2g || !rtlpriv->curveindex_5g ||
		    !rtlpriv->mutex_for_power_on_off || !rtlpriv->mutex_for_hw_init)
			return 1;

		return 0;
	}

	/* The other interface doesn't exist or was not probed yet. */
	rtlpriv->curveindex_2g =
		kzalloc(TARGET_CHNL_NUM_2G * sizeof(*rtlpriv->curveindex_2g),
			GFP_KERNEL);
	rtlpriv->curveindex_5g =
		kzalloc(TARGET_CHNL_NUM_5G * sizeof(*rtlpriv->curveindex_5g),
			GFP_KERNEL);
	rtlpriv->mutex_for_power_on_off =
		kzalloc(sizeof(*rtlpriv->mutex_for_power_on_off), GFP_KERNEL);
	rtlpriv->mutex_for_hw_init =
		kzalloc(sizeof(*rtlpriv->mutex_for_hw_init), GFP_KERNEL);

	if (!rtlpriv->curveindex_2g || !rtlpriv->curveindex_5g ||
	    !rtlpriv->mutex_for_power_on_off || !rtlpriv->mutex_for_hw_init) {
		kfree(rtlpriv->curveindex_2g);
		kfree(rtlpriv->curveindex_5g);
		kfree(rtlpriv->mutex_for_power_on_off);
		kfree(rtlpriv->mutex_for_hw_init);
		rtlpriv->curveindex_2g = NULL;
		rtlpriv->curveindex_5g = NULL;
		rtlpriv->mutex_for_power_on_off = NULL;
		rtlpriv->mutex_for_hw_init = NULL;
		return 1;
	}

	mutex_init(rtlpriv->mutex_for_power_on_off);
	mutex_init(rtlpriv->mutex_for_hw_init);

	return 0;
}

static void rtl92du_deinit_shared_data(struct ieee80211_hw *hw)
{
	struct usb_interface *other_intf = rtl92du_get_other_intf(hw);
	struct rtl_priv *rtlpriv = rtl_priv(hw);

	if (!other_intf || usb_get_intfdata(other_intf)) {
		/* The other interface doesn't exist or was not disconnected yet. */
		kfree(rtlpriv->curveindex_2g);
		kfree(rtlpriv->curveindex_5g);
		if (rtlpriv->mutex_for_power_on_off)
			mutex_destroy(rtlpriv->mutex_for_power_on_off);
		if (rtlpriv->mutex_for_hw_init)
			mutex_destroy(rtlpriv->mutex_for_hw_init);
		kfree(rtlpriv->mutex_for_power_on_off);
		kfree(rtlpriv->mutex_for_hw_init);
	}
}

static int rtl92du_init_sw_vars(struct ieee80211_hw *hw)
{
	const char *fw_name = "rtlwifi/rtl8192dufw.bin";
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	int err;

	if (rtl92du_init_shared_data(hw))
		return 1;

	[...]

	return 0;
}

static void rtl92du_deinit_sw_vars(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);

	kfree(rtlpriv->rtlhal.pfirmware);
	rtlpriv->rtlhal.pfirmware = NULL;

	rtl92du_deinit_shared_data(hw);
}




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux