mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-02 15:21:03 +00:00
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
commit
6de3f7e911
@ -487,16 +487,13 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
|
||||
void iwl_dbgfs_unregister(struct iwl_priv *priv);
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir);
|
||||
#else
|
||||
static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
static inline int iwl_dbgfs_register(struct iwl_priv *priv,
|
||||
struct dentry *dbgfs_dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
@ -2349,24 +2349,19 @@ DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);
|
||||
* Create the debugfs files and directories
|
||||
*
|
||||
*/
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
|
||||
{
|
||||
struct dentry *phyd = priv->hw->wiphy->debugfsdir;
|
||||
struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
|
||||
struct dentry *dir_data, *dir_rf, *dir_debug;
|
||||
|
||||
dir_drv = debugfs_create_dir(name, phyd);
|
||||
if (!dir_drv)
|
||||
return -ENOMEM;
|
||||
priv->debugfs_dir = dbgfs_dir;
|
||||
|
||||
priv->debugfs_dir = dir_drv;
|
||||
|
||||
dir_data = debugfs_create_dir("data", dir_drv);
|
||||
dir_data = debugfs_create_dir("data", dbgfs_dir);
|
||||
if (!dir_data)
|
||||
goto err;
|
||||
dir_rf = debugfs_create_dir("rf", dir_drv);
|
||||
dir_rf = debugfs_create_dir("rf", dbgfs_dir);
|
||||
if (!dir_rf)
|
||||
goto err;
|
||||
dir_debug = debugfs_create_dir("debug", dir_drv);
|
||||
dir_debug = debugfs_create_dir("debug", dbgfs_dir);
|
||||
if (!dir_debug)
|
||||
goto err;
|
||||
|
||||
@ -2412,25 +2407,30 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
/* Calibrations disabled/enabled status*/
|
||||
DEBUGFS_ADD_FILE(calib_disabled, dir_rf, S_IWUSR | S_IRUSR);
|
||||
|
||||
if (iwl_trans_dbgfs_register(priv->trans, dir_debug))
|
||||
goto err;
|
||||
/*
|
||||
* Create a symlink with mac80211. This is not very robust, as it does
|
||||
* not remove the symlink created. The implicit assumption is that
|
||||
* when the opmode exits, mac80211 will also exit, and will remove
|
||||
* this symlink as part of its cleanup.
|
||||
*/
|
||||
if (priv->mac80211_registered) {
|
||||
char buf[100];
|
||||
struct dentry *mac80211_dir, *dev_dir, *root_dir;
|
||||
|
||||
dev_dir = dbgfs_dir->d_parent;
|
||||
root_dir = dev_dir->d_parent;
|
||||
mac80211_dir = priv->hw->wiphy->debugfsdir;
|
||||
|
||||
snprintf(buf, 100, "../../%s/%s", root_dir->d_name.name,
|
||||
dev_dir->d_name.name);
|
||||
|
||||
if (!debugfs_create_symlink("iwlwifi", mac80211_dir, buf))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
IWL_ERR(priv, "Can't create the debugfs directory\n");
|
||||
iwl_dbgfs_unregister(priv);
|
||||
IWL_ERR(priv, "failed to create the dvm debugfs entries\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the debugfs files and directories
|
||||
*
|
||||
*/
|
||||
void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
if (!priv->debugfs_dir)
|
||||
return;
|
||||
|
||||
debugfs_remove_recursive(priv->debugfs_dir);
|
||||
priv->debugfs_dir = NULL;
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
|
||||
}
|
||||
|
||||
hw->wiphy->max_remain_on_channel_duration = 1000;
|
||||
hw->wiphy->max_remain_on_channel_duration = 500;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
|
@ -862,7 +862,8 @@ void iwl_down(struct iwl_priv *priv)
|
||||
* No race since we hold the mutex here and a new one
|
||||
* can't come in at this time.
|
||||
*/
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT)
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
|
||||
exit_pending =
|
||||
test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
@ -994,7 +995,11 @@ static void iwl_bg_restart(struct work_struct *data)
|
||||
iwlagn_prepare_restart(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl_cancel_deferred_work(priv);
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
else
|
||||
IWL_ERR(priv,
|
||||
"Cannot request restart before registrating with mac80211");
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
@ -1222,7 +1227,8 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||
|
||||
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw)
|
||||
const struct iwl_fw *fw,
|
||||
struct dentry *dbgfs_dir)
|
||||
{
|
||||
struct iwl_priv *priv;
|
||||
struct ieee80211_hw *hw;
|
||||
@ -1466,13 +1472,17 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
if (iwlagn_mac_setup_register(priv, &fw->ucode_capa))
|
||||
goto out_destroy_workqueue;
|
||||
|
||||
if (iwl_dbgfs_register(priv, DRV_NAME))
|
||||
IWL_ERR(priv,
|
||||
"failed to create debugfs files. Ignoring error\n");
|
||||
if (iwl_dbgfs_register(priv, dbgfs_dir))
|
||||
goto out_mac80211_unregister;
|
||||
|
||||
return op_mode;
|
||||
|
||||
out_mac80211_unregister:
|
||||
iwlagn_mac_unregister(priv);
|
||||
out_destroy_workqueue:
|
||||
iwl_tt_exit(priv);
|
||||
iwl_testmode_free(priv);
|
||||
iwl_cancel_deferred_work(priv);
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
iwl_uninit_drv(priv);
|
||||
@ -1493,8 +1503,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
|
||||
|
||||
iwl_dbgfs_unregister(priv);
|
||||
|
||||
iwl_testmode_free(priv);
|
||||
iwlagn_mac_unregister(priv);
|
||||
|
||||
|
@ -150,7 +150,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
|
||||
|
||||
if (!(flags & CMD_ASYNC)) {
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD;
|
||||
might_sleep();
|
||||
}
|
||||
|
||||
|
@ -433,7 +433,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
|
||||
* only. Check this here.
|
||||
*/
|
||||
if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON &&
|
||||
tid_data->agg.state != IWL_AGG_OFF,
|
||||
tid_data->agg.state != IWL_AGG_OFF,
|
||||
"Tx while agg.state = %d", tid_data->agg.state))
|
||||
goto drop_unlock_sta;
|
||||
|
||||
|
@ -101,6 +101,10 @@ MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static struct dentry *iwl_dbgfs_root;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct iwl_drv - drv common data
|
||||
* @list: list of drv structures using this opmode
|
||||
@ -126,6 +130,12 @@ struct iwl_drv {
|
||||
char firmware_name[25]; /* name of firmware file to load */
|
||||
|
||||
struct completion request_firmware_complete;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct dentry *dbgfs_drv;
|
||||
struct dentry *dbgfs_trans;
|
||||
struct dentry *dbgfs_op_mode;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DVM_OP_MODE 0
|
||||
@ -194,7 +204,8 @@ static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
||||
static void iwl_req_fw_callback(const struct firmware *ucode_raw,
|
||||
void *context);
|
||||
|
||||
#define UCODE_EXPERIMENTAL_INDEX 100
|
||||
#define UCODE_EXPERIMENTAL_TAG "exp"
|
||||
@ -231,7 +242,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
|
||||
return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
|
||||
drv->trans->dev,
|
||||
GFP_KERNEL, drv, iwl_ucode_callback);
|
||||
GFP_KERNEL, drv, iwl_req_fw_callback);
|
||||
}
|
||||
|
||||
struct fw_img_parsing {
|
||||
@ -759,13 +770,57 @@ static int validate_sec_sizes(struct iwl_drv *drv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *
|
||||
_iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
||||
{
|
||||
const struct iwl_op_mode_ops *ops = op->ops;
|
||||
struct dentry *dbgfs_dir = NULL;
|
||||
struct iwl_op_mode *op_mode = NULL;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||
drv->dbgfs_drv);
|
||||
if (!drv->dbgfs_op_mode) {
|
||||
IWL_ERR(drv,
|
||||
"failed to create opmode debugfs directory\n");
|
||||
return op_mode;
|
||||
}
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
#endif
|
||||
|
||||
op_mode = ops->start(drv->trans, drv->cfg, &drv->fw, dbgfs_dir);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (!op_mode) {
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return op_mode;
|
||||
}
|
||||
|
||||
static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
||||
{
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode) {
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
drv->op_mode = NULL;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_ucode_callback - callback when firmware was loaded
|
||||
* iwl_req_fw_callback - callback when firmware was loaded
|
||||
*
|
||||
* If loaded successfully, copies the firmware into buffers
|
||||
* for the card to fetch (via DMA).
|
||||
*/
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
{
|
||||
struct iwl_drv *drv = context;
|
||||
struct iwl_fw *fw = &drv->fw;
|
||||
@ -908,8 +963,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
list_add_tail(&drv->list, &op->drv);
|
||||
|
||||
if (op->ops) {
|
||||
const struct iwl_op_mode_ops *ops = op->ops;
|
||||
drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw);
|
||||
drv->op_mode = _iwl_op_mode_start(drv, op);
|
||||
|
||||
if (!drv->op_mode) {
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
@ -969,14 +1023,43 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
init_completion(&drv->request_firmware_complete);
|
||||
INIT_LIST_HEAD(&drv->list);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the device debugfs entries. */
|
||||
drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
|
||||
iwl_dbgfs_root);
|
||||
|
||||
if (!drv->dbgfs_drv) {
|
||||
IWL_ERR(drv, "failed to create debugfs directory\n");
|
||||
goto err_free_drv;
|
||||
}
|
||||
|
||||
/* Create transport layer debugfs dir */
|
||||
drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv);
|
||||
|
||||
if (!drv->trans->dbgfs_dir) {
|
||||
IWL_ERR(drv, "failed to create transport debugfs directory\n");
|
||||
goto err_free_dbgfs;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = iwl_request_firmware(drv, true);
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Couldn't request the fw\n");
|
||||
kfree(drv);
|
||||
drv = NULL;
|
||||
goto err_fw;
|
||||
}
|
||||
|
||||
return drv;
|
||||
|
||||
err_fw:
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
err_free_dbgfs:
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
err_free_drv:
|
||||
#endif
|
||||
kfree(drv);
|
||||
drv = NULL;
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
@ -984,9 +1067,7 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
||||
{
|
||||
wait_for_completion(&drv->request_firmware_complete);
|
||||
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode)
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
_iwl_op_mode_stop(drv);
|
||||
|
||||
iwl_dealloc_ucode(drv);
|
||||
|
||||
@ -1000,6 +1081,10 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
||||
list_del(&drv->list);
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
#endif
|
||||
|
||||
kfree(drv);
|
||||
}
|
||||
|
||||
@ -1022,15 +1107,18 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
|
||||
{
|
||||
int i;
|
||||
struct iwl_drv *drv;
|
||||
struct iwlwifi_opmode_table *op;
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) {
|
||||
if (strcmp(iwlwifi_opmode_table[i].name, name))
|
||||
op = &iwlwifi_opmode_table[i];
|
||||
if (strcmp(op->name, name))
|
||||
continue;
|
||||
iwlwifi_opmode_table[i].ops = ops;
|
||||
list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
|
||||
drv->op_mode = ops->start(drv->trans, drv->cfg,
|
||||
&drv->fw);
|
||||
op->ops = ops;
|
||||
/* TODO: need to handle exceptional case */
|
||||
list_for_each_entry(drv, &op->drv, list)
|
||||
drv->op_mode = _iwl_op_mode_start(drv, op);
|
||||
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
return 0;
|
||||
}
|
||||
@ -1051,12 +1139,9 @@ void iwl_opmode_deregister(const char *name)
|
||||
iwlwifi_opmode_table[i].ops = NULL;
|
||||
|
||||
/* call the stop routine for all devices */
|
||||
list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) {
|
||||
if (drv->op_mode) {
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
drv->op_mode = NULL;
|
||||
}
|
||||
}
|
||||
list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
|
||||
_iwl_op_mode_stop(drv);
|
||||
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
return;
|
||||
}
|
||||
@ -1076,6 +1161,14 @@ static int __init iwl_drv_init(void)
|
||||
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
||||
pr_info(DRV_COPYRIGHT "\n");
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the root of iwlwifi debugfs subsystem. */
|
||||
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
|
||||
|
||||
if (!iwl_dbgfs_root)
|
||||
return -EFAULT;
|
||||
#endif
|
||||
|
||||
return iwl_pci_register_driver();
|
||||
}
|
||||
module_init(iwl_drv_init);
|
||||
@ -1083,6 +1176,10 @@ module_init(iwl_drv_init);
|
||||
static void __exit iwl_drv_exit(void)
|
||||
{
|
||||
iwl_pci_unregister_driver();
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(iwl_dbgfs_root);
|
||||
#endif
|
||||
}
|
||||
module_exit(iwl_drv_exit);
|
||||
|
||||
|
@ -90,9 +90,9 @@
|
||||
* 4) The bus specific component configures the bus
|
||||
* 5) The bus specific component calls to the drv bus agnostic part
|
||||
* (iwl_drv_start)
|
||||
* 6) iwl_drv_start fetches the fw ASYNC, iwl_ucode_callback
|
||||
* 7) iwl_ucode_callback parses the fw file
|
||||
* 8) iwl_ucode_callback starts the wifi implementation to matches the fw
|
||||
* 6) iwl_drv_start fetches the fw ASYNC, iwl_req_fw_callback
|
||||
* 7) iwl_req_fw_callback parses the fw file
|
||||
* 8) iwl_req_fw_callback starts the wifi implementation to matches the fw
|
||||
*/
|
||||
|
||||
struct iwl_drv;
|
||||
|
@ -134,7 +134,8 @@ struct iwl_cfg;
|
||||
struct iwl_op_mode_ops {
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw);
|
||||
const struct iwl_fw *fw,
|
||||
struct dentry *dbgfs_dir);
|
||||
void (*stop)(struct iwl_op_mode *op_mode);
|
||||
int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
@ -184,14 +184,20 @@ struct iwl_rx_packet {
|
||||
* @CMD_SYNC: The caller will be stalled until the fw responds to the command
|
||||
* @CMD_ASYNC: Return right away and don't want for the response
|
||||
* @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
|
||||
* response.
|
||||
* response. The caller needs to call iwl_free_resp when done.
|
||||
* @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the
|
||||
* response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be
|
||||
* copied. The pointer passed to the response handler is in the transport
|
||||
* ownership and don't need to be freed by the op_mode. This also means
|
||||
* that the pointer is invalidated after the op_mode's handler returns.
|
||||
* @CMD_ON_DEMAND: This command is sent by the test mode pipe.
|
||||
*/
|
||||
enum CMD_MODE {
|
||||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_ON_DEMAND = BIT(2),
|
||||
CMD_WANT_HCMD = BIT(2),
|
||||
CMD_ON_DEMAND = BIT(3),
|
||||
};
|
||||
|
||||
#define DEF_CMD_PAYLOAD_SIZE 320
|
||||
@ -460,6 +466,8 @@ struct iwl_trans {
|
||||
size_t dev_cmd_headroom;
|
||||
char dev_cmd_pool_name[50];
|
||||
|
||||
struct dentry *dbgfs_dir;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
char trans_specific[0] __aligned(sizeof(void *));
|
||||
|
@ -282,8 +282,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (!trans_pcie->drv)
|
||||
goto out_free_trans;
|
||||
|
||||
/* register transport layer debugfs here */
|
||||
if (iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir))
|
||||
goto out_free_drv;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_drv:
|
||||
iwl_drv_stop(trans_pcie->drv);
|
||||
out_free_trans:
|
||||
iwl_trans_pcie_free(iwl_trans);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
@ -184,6 +184,7 @@ struct iwl_queue {
|
||||
|
||||
struct iwl_pcie_tx_queue_entry {
|
||||
struct iwl_device_cmd *cmd;
|
||||
struct iwl_device_cmd *copy_cmd;
|
||||
struct sk_buff *skb;
|
||||
struct iwl_cmd_meta meta;
|
||||
};
|
||||
|
@ -421,13 +421,23 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
|
||||
index = SEQ_TO_INDEX(sequence);
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
|
||||
if (reclaim)
|
||||
cmd = txq->entries[cmd_index].cmd;
|
||||
else
|
||||
if (reclaim) {
|
||||
struct iwl_pcie_tx_queue_entry *ent;
|
||||
ent = &txq->entries[cmd_index];
|
||||
cmd = ent->copy_cmd;
|
||||
WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
|
||||
} else {
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
|
||||
|
||||
if (reclaim) {
|
||||
/* The original command isn't needed any more */
|
||||
kfree(txq->entries[cmd_index].copy_cmd);
|
||||
txq->entries[cmd_index].copy_cmd = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* After here, we should always check rxcb._page_stolen,
|
||||
* if it is true then one of the handlers took the page.
|
||||
|
@ -492,10 +492,11 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
|
||||
iwl_tx_queue_unmap(trans, txq_id);
|
||||
|
||||
/* De-alloc array of command/tx buffers */
|
||||
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < txq->q.n_window; i++)
|
||||
for (i = 0; i < txq->q.n_window; i++) {
|
||||
kfree(txq->entries[i].cmd);
|
||||
kfree(txq->entries[i].copy_cmd);
|
||||
}
|
||||
|
||||
/* De-alloc circular buffer of TFDs */
|
||||
if (txq->q.n_bd) {
|
||||
@ -896,6 +897,7 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
|
||||
static int iwl_prepare_card_hw(struct iwl_trans *trans)
|
||||
{
|
||||
int ret;
|
||||
int t = 0;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
|
||||
|
||||
@ -908,17 +910,15 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_PREPARE);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
|
||||
do {
|
||||
ret = iwl_set_hw_ready(trans);
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
usleep_range(200, 1000);
|
||||
t += 200;
|
||||
} while (t < 150000);
|
||||
|
||||
/* HW should be ready by now, check again. */
|
||||
ret = iwl_set_hw_ready(trans);
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1769,7 +1769,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
|
||||
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
if (!debugfs_create_file(#name, mode, parent, trans, \
|
||||
&iwl_dbgfs_##name##_ops)) \
|
||||
return -ENOMEM; \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
/* file operation */
|
||||
@ -2033,6 +2033,10 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
||||
DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#else
|
||||
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
||||
|
@ -521,7 +521,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
u16 copy_size, cmd_size;
|
||||
bool had_nocopy = false;
|
||||
int i;
|
||||
u8 *cmd_dest;
|
||||
u32 cmd_pos;
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
|
||||
const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
|
||||
int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
|
||||
@ -584,15 +584,31 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
INDEX_TO_SEQ(q->write_ptr));
|
||||
|
||||
/* and copy the data that needs to be copied */
|
||||
|
||||
cmd_dest = out_cmd->payload;
|
||||
cmd_pos = offsetof(struct iwl_device_cmd, payload);
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
if (!cmd->len[i])
|
||||
continue;
|
||||
if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
|
||||
break;
|
||||
memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
|
||||
cmd_dest += cmd->len[i];
|
||||
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
|
||||
cmd_pos += cmd->len[i];
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(txq->entries[idx].copy_cmd);
|
||||
|
||||
/*
|
||||
* since out_cmd will be the source address of the FH, it will write
|
||||
* the retry count there. So when the user needs to receivce the HCMD
|
||||
* that corresponds to the response in the response handler, it needs
|
||||
* to set CMD_WANT_HCMD.
|
||||
*/
|
||||
if (cmd->flags & CMD_WANT_HCMD) {
|
||||
txq->entries[idx].copy_cmd =
|
||||
kmemdup(out_cmd, cmd_pos, GFP_ATOMIC);
|
||||
if (unlikely(!txq->entries[idx].copy_cmd)) {
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_HC(trans,
|
||||
|
Loading…
Reference in New Issue
Block a user